home *** CD-ROM | disk | FTP | other *** search
/ Future Workshop / Future Workshop.iso / multimed / qtw111 / pviewer / pictwnd.c < prev    next >
C/C++ Source or Header  |  1994-01-11  |  95KB  |  2,416 lines

  1.  
  2. // ---------------------------------------------------------------------
  3. //
  4. // PictWnd.c - Picture Viewer - QuickTime for Windows
  5. //
  6. //             Version 1.0
  7. //
  8. //             (c) 1988-1992 Apple Computer, Inc. All Rights Reserved.
  9. //
  10. // ---------------------------------------------------------------------
  11.  
  12.  
  13. // Includes
  14. // --------
  15. #include <Windows.H>   // Required by Windows
  16. #include <commdlg.h>   // Required for PRINTDLG struct
  17. #include <stdio.h>     // Required for sprintf routine
  18. #include <stdlib.h>    // Required for fullpath routine
  19. #include <sys\types.h> // Required for stat.h
  20. #include <sys\stat.h>  // Required for _stat routine
  21.  
  22. #include <qtw.h>    // Interface to QuickTime
  23. #include <qtole.h>  // Interface to qtole dll
  24. #include "common.h" // Interface to common.c
  25.  
  26. #include "viewer.h"  // Interface to other *.c files
  27. #include "viewer.hr" // Defines used in *.rc files
  28. #include "picture.h" // Interface to child window processing
  29.  
  30. // Constants
  31. // ---------
  32. #define GETINFOPICTUREPROP    "Picture" // Used in initializing info dialog
  33. #define SIZE_COLOR_TABLE     ( 256 * sizeof( RGBQUAD ))
  34.  
  35. // Message-Persistent Data
  36. // -----------------------
  37. static struct // Hungarian notation: g
  38.   { WORD      wPictureCount;     // Used during enumeration for
  39.                                  // duplication checking
  40.     BOOL      bCreating;         //   "    "       "
  41.     HWND      hwndFirstDup;      //   "    "       "
  42.     HICON     hpictIcon;         // Picture wnd icon
  43.     HPALETTE  hpalCurrentSystem; // Current system palette
  44.     RECT      rcSelection;       // Selection rect
  45.  
  46.   } g;
  47.  
  48. // Macros
  49. // ----------------------------
  50. #define ISKEYDOWN( vKey )    ( GetKeyState( (int) (vKey) ) < 0 )
  51. // Next macro is from windowsx.h
  52. #define GlobalPtrHandle(lp)   \
  53.                ( (HGLOBAL) LOWORD( GlobalHandle( SELECTOROF( lp ))))
  54.  
  55.  
  56. // Exported callback function
  57. // ----------------------------
  58. BOOL __export CALLBACK GetInfoDlgProc     (HWND, UINT, WPARAM, LPARAM);
  59. BOOL __export CALLBACK CheckDupEnumProc   (HWND, LPARAM);
  60.  
  61.  
  62. // Internal Function Declarations
  63. // ------------------------------
  64. static LONG    NEAR ViewerPictureCreate      (HWND, LPARAM );
  65. static LONG    NEAR ViewerEditCommands       (HWND, WPARAM, WORD);
  66. static LONG    NEAR ViewerImageCommands      (HWND, WPARAM, WORD);
  67. static LONG    NEAR PrintPicture             (HWND, LPPRINTDLG);
  68. static VOID    NEAR FillPictureInfo          (HWND, NPPICTUREDATA);
  69. static VOID    NEAR UpdateInfoFileName       (HWND, NPPICTUREDATA);
  70. static VOID    NEAR UpdateInfoCurrentSize    (HWND, NPPICTUREDATA);
  71. static LONG    NEAR InitializePopupMenus     (HWND, HMENU, int);
  72. static LONG    NEAR PaintThePicture          (HWND);
  73. static LONG    NEAR PaintTheIcon             (HWND);
  74. static LONG    NEAR KeyDownMessage           (HWND, WPARAM, LPARAM);
  75. static BOOL    NEAR BuildIconBitmap          (HWND, NPPICTUREDATA);
  76.  
  77. static BOOL    NEAR InitSelection            (HWND, POINT);
  78. static VOID    NEAR MoveTheSelectRect        (HWND, POINT);
  79. static VOID    NEAR EndTheSelection          (HWND);
  80. static VOID    NEAR DrawSelectionRect        (HWND, HDC, NPPICTUREDATA);
  81.  
  82. static VOID    NEAR SetOptionsDefaults       (HWND, NPPICTUREDATA);
  83. static VOID    NEAR PopulateOptionsStruct    (HWND, NPPICTUREDATA);
  84.  
  85.  
  86. // Function: ViewerPictureWndProc - Viewer picture Window Procedure
  87. // --------------------------------------------------------------------
  88. // Parameters: As required by Microsoft Windows
  89. //
  90. // Returns:    Via DefMDIChildProc
  91. // --------------------------------------------------------------------
  92. LONG __export CALLBACK ViewerPictureWndProc
  93.     (HWND hwndPicture, UINT message, WPARAM wParam, LPARAM lParam)
  94.  
  95. {
  96.     NPPICTUREDATA    pPictureData;      // Temp -> to picture data struct
  97.     HPICTUREDATA     hPictureData;      // Temp handle to picture data
  98.     WNDENUMPROC      lpfnEnumPictures;  // -> enumeration proc
  99.     NPPICTUREDATA    pFirstPictureData; // Temp -> to picture data
  100.                                         // struct. Used during duplication
  101.                                         // processing
  102.     HDC              hdc;               // Window hdc
  103.     HPALETTE         hpalSave;          // Prev palette
  104.     POINT            ptCursor;          // Cursor position used in grow box
  105.     LPNCCALCSIZE_PARAMS lpncsp;         // -> NCCCALCSIZE_PARAMS struct
  106.     LPQTOLE_OLEDATA  lpOleData;         // -> ole data
  107.  
  108.     static BOOL      bDragging;  // Flag set when using grow box
  109.     static BOOL      bSelecting; // Flag set when making a selection
  110.  
  111.     switch( message ) {
  112.         case WM_CREATE:
  113.             // Load picture frame icon used by all instances
  114.             if( !g.hpictIcon )
  115.                 g.hpictIcon = LoadIcon( ViewerQueryResources(),
  116.                 MAKEINTRESOURCE( VIEWER_PICT_ICON ));
  117.             return ViewerPictureCreate( hwndPicture , lParam );
  118.  
  119.         case WM_SIZE:
  120.             // Turn off the max size limits set during
  121.             // WM_NCLBUTTONDOWN processing
  122.             if( bDragging ) {
  123.                 LimitTheDragSize( hwndPicture, bDragging = FALSE );
  124.             }
  125.  
  126.             // This routine also updates scrolling parameters
  127.             ResizeKids( hwndPicture, LOWORD( lParam ), HIWORD( lParam ));
  128.  
  129.             break; // Break to DefMDIChildProc
  130.  
  131.  
  132.         // We don't use the CS_HREDRAW | CS_VREDRAW so we need to
  133.         // tell when to repaint the entire picture. We repaint the whole
  134.         // thing if the UL corner moves or either of the scroll
  135.         // bars is enabled.
  136.         case WM_NCCALCSIZE:
  137.             if( wParam ) {
  138.                 lpncsp = (LPNCCALCSIZE_PARAMS) lParam;
  139.                 if( !( pPictureData =
  140.                     (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) ||
  141.                     ( lpncsp->rgrc[0].left != lpncsp->rgrc[1].left ) ||
  142.                     ( lpncsp->rgrc[0].top  != lpncsp->rgrc[1].top ) ||
  143.                     IsWindowEnabled( pPictureData->spmsHScroll.hwnd ) ||
  144.                     IsWindowEnabled( pPictureData->spmsVScroll.hwnd )) {
  145.                     InvalidateRect( hwndPicture, NULL, FALSE );
  146.                 }
  147.                 else if( ( lpncsp->rgrc[0].right  > lpncsp->rgrc[1].right ) ||
  148.                     ( lpncsp->rgrc[0].bottom > lpncsp->rgrc[1].bottom )) { // Paint out the grow box. At this point, the grow box rect
  149.                                                                            // still contains the old rect since this message occurs
  150.                                                                            // before the WM_SIZE message
  151.                     InvalidateRect( hwndPicture,
  152.                         &pPictureData->rcGrowBox, FALSE );
  153.                 }
  154.             }
  155.  
  156.             break; // Break to DefMDIChildProc
  157.  
  158.         // This tells windows to treat the grow box like the
  159.         // bottom right window frame
  160.         case WM_NCHITTEST:
  161.             if( !IsZoomed( hwndPicture )) {
  162.                 ptCursor = MAKEPOINT( lParam );
  163.                 ScreenToClient( hwndPicture, &ptCursor );
  164.                 if( IsInGrowBox( hwndPicture, ptCursor ))
  165.                     return HTBOTTOMRIGHT;
  166.             }
  167.  
  168.             break; // Break to DefMDIChildProc
  169.  
  170.  
  171.         // Set the cursor to the arrow cursor in the grow box
  172.         // Because of the WM_NCHITTEST processing we do, Windows
  173.         // thinks it is in the corner border and will set the
  174.         // cursor to the diagonal arrow.
  175.         case WM_SETCURSOR:
  176.             if( LOWORD( lParam ) == HTBOTTOMRIGHT ) {
  177.                 GetCursorPos( &ptCursor );
  178.                 ScreenToClient( hwndPicture, &ptCursor );
  179.                 if( IsInGrowBox( hwndPicture, ptCursor )) {
  180.                     SetCursor( LoadCursor( NULL, IDC_ARROW ));
  181.                     return 1L;
  182.                 }
  183.             }
  184.             break; // Break to DefMDIChildProc
  185.  
  186.         // Limit the window size so that the grow box resized window
  187.         // stays inside the MDI client rect
  188.         case WM_NCLBUTTONDOWN:
  189.             if( wParam == HTBOTTOMRIGHT ) {
  190.                 ptCursor = MAKEPOINT( lParam );
  191.                 ScreenToClient( hwndPicture, &ptCursor );
  192.                 if( IsInGrowBox( hwndPicture, ptCursor )) {
  193.                     LimitTheDragSize( hwndPicture, bDragging = TRUE );
  194.                 }
  195.             }
  196.  
  197.             break; // Break to DefMDIChildProc
  198.  
  199.  
  200.         // WM_LBUTTONDOWN, WM_MOUSEMOVE, WM_LBUTTONUP are used to implement
  201.         // grow box resizing of the frame window when the window is maximized
  202.         case WM_LBUTTONDOWN:
  203.             if( IsZoomed( hwndPicture ) &&
  204.                 !IsZoomed( ViewerQueryFrameWindow()) &&
  205.                 IsInGrowBox( hwndPicture, MAKEPOINT( lParam )) &&
  206.                 ( bDragging = InitMaxWndGrowBoxResize
  207.                 ( hwndPicture, MAKEPOINT( lParam )))) {
  208.                 SetCapture( hwndPicture );
  209.             }
  210.             else if( bSelecting = InitSelection
  211.                 ( hwndPicture, MAKEPOINT( lParam ))) {
  212.                 SetCapture( hwndPicture );
  213.             }
  214.  
  215.             return 0L;
  216.  
  217.         case WM_MOUSEMOVE:
  218.             if( bDragging && IsZoomed( hwndPicture )) {
  219.                 MoveTheFrameRect( hwndPicture, MAKEPOINT( lParam ));
  220.             }
  221.             else if( bSelecting ) {
  222.                 MoveTheSelectRect( hwndPicture, MAKEPOINT( lParam ));
  223.             }
  224.  
  225.             return 0L;
  226.  
  227.         case WM_LBUTTONUP:
  228.             if( bDragging && IsZoomed( hwndPicture )) {
  229.                 EndMaxWndGrowBoxResize( hwndPicture );
  230.                 bDragging = FALSE;
  231.                 ReleaseCapture();
  232.             }
  233.             else if( bSelecting ) {
  234.                 EndTheSelection( hwndPicture );
  235.                 bSelecting = FALSE;
  236.                 ReleaseCapture();
  237.             }
  238.  
  239.             return 0L;
  240.  
  241.  
  242.         case WM_NCACTIVATE:
  243.             if( !( pPictureData =
  244.                 (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  245.                 break; // Break to DefMDIChildProc
  246.  
  247.             if( (BOOL) wParam ) { // Set flag to disable the scroll bar processing. Although this
  248.                                   // is only necessary in the case of palettized devices, it is
  249.                                   // done in all cases in order to have a consistent user interface.
  250.                                   // This disabling is necessary in order to avoid a problem with
  251.                                   // simultaneous scrolling and palette switching that leaves a
  252.                                   // portion of the picture incorrectly updated.
  253.                                   // The visual effect of this disabling is that clicking on a
  254.                                   // scroll bar will activate the window but will not cause the
  255.                                   // scolling to actually occur.
  256.  
  257.                 pPictureData->bScrollWaitForPaint = TRUE;
  258.  
  259.                 // Realize palette if activating and is palettized device
  260.                 if( ViewerIsPalettized()) {
  261.                     if( pPictureData->hpalPicture &&
  262.                         ( hdc = GetDC( hwndPicture ))) {
  263.                         hpalSave = SelectPalette
  264.                             ( hdc, pPictureData->hpalPicture, 0 );
  265.  
  266.                         StoreCurrentSystemPalette
  267.                             ( pPictureData->hpalPicture );
  268.                         RealizePalette( hdc );
  269.  
  270.                         SelectPalette( hdc, hpalSave, 0 );
  271.                         ReleaseDC( hwndPicture, hdc );
  272.  
  273.                         InvalidateRect( hwndPicture, NULL, FALSE );
  274.                     }
  275.                     else if( GetUpdateRect( hwndPicture, NULL, FALSE ))
  276.                         InvalidateRect( hwndPicture, NULL, FALSE );
  277.                 }
  278.                 else { // Post message to reable scrolling because generally will
  279.                        // not get a WM_PAINT message. Don't want to use
  280.                        // InvalidateRect() because it will generate an unnessary
  281.                        // repaint.
  282.                     PostMessage( hwndPicture, WM_VIEWER_REENABLESCROLL, 0, 0L );
  283.                 }
  284.             }
  285.  
  286.             break; // Break to DefMDIChildProc
  287.  
  288.         case WM_SYSCOMMAND:
  289.             // Each picture needs an icon bitmap. We build it here
  290.             // because the window must have first realized the palette.
  291.             // This message appears after the WM_NCACTIVATE
  292.             // message for this window and before the WM_NCACTIVATE
  293.             // for the window that will eventually be activated.
  294.             // This bitmap will be created and saved the first time
  295.             // the window is iconized
  296.             if( ( wParam == SC_MINIMIZE ) &&
  297.                 ( pPictureData =
  298.                 (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) &&
  299.                 !pPictureData->hbitmapIcon && !pPictureData->lpDIBIconMem ) {
  300.                 BuildIconBitmap( hwndPicture, pPictureData );
  301.             }
  302.  
  303.             break; // Break to DefMDIChildProc
  304.  
  305.         case WM_COMMAND:
  306.             switch( wParam ) {
  307.                 case VIEWER_EDIT_COPYPICTURE: // edit menu popup
  308.                 case VIEWER_EDIT_OPTIONS:
  309.                 case VIEWER_EDIT_CANCELSEL:
  310.                     return ViewerEditCommands
  311.                         ( hwndPicture, wParam, HIWORD (lParam));
  312.  
  313.                 case VIEWER_IMAGE_GETINFO: // image menu popup
  314.                 case VIEWER_IMAGE_HALFSIZE:
  315.                 case VIEWER_IMAGE_NORMALSIZE:
  316.                 case VIEWER_IMAGE_DOUBLESIZE:
  317.                     return ViewerImageCommands
  318.                         ( hwndPicture, wParam, HIWORD( lParam ));
  319.  
  320.                 default:
  321.                     break; // Break to DefMDIChildProc
  322.             }
  323.  
  324.             break;
  325.  
  326.         case WM_KEYDOWN:
  327.             return KeyDownMessage( hwndPicture, wParam, lParam );
  328.  
  329.         // WM_USER messages
  330.  
  331.         case WM_VIEWER_PRINTPICTURE:
  332.             return PrintPicture( hwndPicture, (LPPRINTDLG) lParam );
  333.  
  334.         case WM_VIEWER_INITPOPUPS:
  335.             return InitializePopupMenus
  336.                 ( hwndPicture, (HMENU) wParam, (int) LOWORD( lParam ));
  337.  
  338.         case WM_VIEWER_REENABLESCROLL:
  339.             if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  340.                 pPictureData->bScrollWaitForPaint = FALSE;
  341.             return 0L;
  342.  
  343.         // end WM_USER messages
  344.  
  345.  
  346.         case WM_ERASEBKGND:
  347.             // If there is a picture, let it deal with the background in
  348.             // WM_PAINT
  349.             return ((pPictureData =
  350.                 (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) != NULL );
  351.  
  352.         case WM_HSCROLL:
  353.             if( !( pPictureData = (NPPICTUREDATA)
  354.                 GetWindowWord( hwndPicture, 0 )) ||
  355.                 pPictureData->bScrollWaitForPaint ) {
  356.                 return 0L;
  357.             }
  358.             else {
  359.                 return ProcessHorzScroll
  360.                     ( hwndPicture, (WORD) wParam, LOWORD( lParam ));
  361.             }
  362.  
  363.         case WM_VSCROLL:
  364.             if( !( pPictureData = (NPPICTUREDATA)
  365.                 GetWindowWord( hwndPicture, 0 )) ||
  366.                 pPictureData->bScrollWaitForPaint ) {
  367.                 return 0L;
  368.             }
  369.             else {
  370.                 return ProcessVertScroll
  371.                     ( hwndPicture, (WORD) wParam, LOWORD( lParam ));
  372.             }
  373.  
  374.         case WM_GETMINMAXINFO:
  375.             SetMinMaxInfo( (MINMAXINFO FAR*) lParam );
  376.             break; // Break to DefMDIChildProc
  377.  
  378.         case WM_QUERYDRAGICON:
  379.             return MAKELONG( g.hpictIcon, 0 );
  380.  
  381.         case WM_PAINT:
  382.             if( IsIconic( hwndPicture ))
  383.                 return PaintTheIcon( hwndPicture );
  384.             else {
  385.                 if( PaintThePicture( hwndPicture )) { // Draw picture failed so close window
  386.                     PostMessage( hwndPicture, WM_CLOSE, 0, 0L );
  387.                 }
  388.                 else if( pPictureData = (NPPICTUREDATA)
  389.                     GetWindowWord( hwndPicture, 0 ))
  390.                     pPictureData->bScrollWaitForPaint = FALSE;
  391.  
  392.                 return 0L;
  393.             }
  394.  
  395.         case WM_DESTROY:
  396.             if( ( pPictureData = (NPPICTUREDATA)
  397.                 GetWindowWord( hwndPicture, 0 )) &&
  398.                 ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer ) {
  399.                 PopulateOptionsStruct( hwndPicture, pPictureData );
  400.                 if( !QTOLE_ClosingDocWnd( lpOleData,
  401.                     (LPQTOLE_OPTIONS) &pPictureData->qtoleOptions ))
  402.                     return 0L;
  403.             }
  404.  
  405.             break; // break to DefMDIChildProc
  406.  
  407.         // Process WM_NCDESTROY instead of WM_DESTROY so that child controls
  408.         // get WM_DESTROY messages before the stuff in here get executed
  409.         case WM_NCDESTROY:
  410.             if( !(pPictureData =
  411.                 (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )))
  412.                 break;
  413.  
  414.             if( pPictureData->hwndGetInfo )
  415.                 DestroyWindow( pPictureData->hwndGetInfo );
  416.  
  417.             if( pPictureData->phPicture != NULL)
  418.                 DisposePicture( pPictureData->phPicture );
  419.  
  420.             if( pPictureData->hpalPicture )
  421.                 DeleteObject( pPictureData->hpalPicture );
  422.  
  423.             if( pPictureData->hbitmapIcon )
  424.                 DeleteObject( pPictureData->hbitmapIcon );
  425.             if( pPictureData->lpDIBIconMem ) {
  426.                 GlobalUnlock( GlobalPtrHandle( pPictureData->lpDIBIconMem ));
  427.                 GlobalFree( GlobalPtrHandle( pPictureData->lpDIBIconMem ));
  428.             }
  429.  
  430.             // Last instance destroys icon stuff
  431.             if( ViewerQueryNumPictures() <= 1 ) {
  432.                 if( g.hpictIcon ) {
  433.                     DestroyIcon( g.hpictIcon );
  434.                     g.hpictIcon = NULL;
  435.                 }
  436.                 g.hpalCurrentSystem = NULL;
  437.                 DestroyGrowBoxBitmap();
  438.             }
  439.             else // Check for duplicates
  440.             {
  441.                 g.wPictureCount = 0;
  442.                 g.bCreating     = FALSE;
  443.                 g.hwndFirstDup  = NULL;
  444.                 if( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  445.                     ( (FARPROC) CheckDupEnumProc, ViewerQueryInstance())) {
  446.                     EnumChildWindows( ViewerQueryClientWindow(),
  447.                         lpfnEnumPictures, MAKELPARAM( hwndPicture, 0 ));
  448.                     FreeProcInstance( (FARPROC) lpfnEnumPictures );
  449.  
  450.                     // if no dups, eliminate :1 on first
  451.                     // hwndFirstDup is set in CheckDupEnumProc
  452.                     if( ( g.wPictureCount == 1 ) && g.hwndFirstDup &&
  453.                         ( pFirstPictureData = (NPPICTUREDATA)
  454.                         GetWindowWord( g.hwndFirstDup, 0 ))) {
  455.                         pFirstPictureData->wDuplicationIndex = 0;
  456.                         SetWindowText( g.hwndFirstDup,
  457.                             pFirstPictureData->szPictureName );
  458.                     }
  459.                 }
  460.             }
  461.  
  462.             LocalUnlock( hPictureData =
  463.                 (HPICTUREDATA) LocalHandle( pPictureData ));
  464.             LocalFree( hPictureData );
  465.             SetWindowWord( hwndPicture, 0, 0 ); // Set this to 0 for any
  466.                                                 // subsequent messages
  467.  
  468.             SendMessage( ViewerQueryFrameWindow(),
  469.                 WM_VIEWER_PICTUREDELETED, (WPARAM) hwndPicture, 0L );
  470.  
  471.             break; // break to DefMDIChildProc
  472.  
  473.     }
  474.  
  475.     return DefMDIChildProc( hwndPicture, message, wParam, lParam );
  476. }
  477.  
  478.  
  479. // Function: ViewerPictureCreate - process WM_CREATE message
  480. // --------------------------------------------------------------------
  481. // Parameters: HWND       hwndPicture      Handle of picture window
  482. //             LPARAM     lParam           lParam of WM_CREATE message
  483. //
  484. // Returns:    0L if OK, else returns -1L to kill app
  485. // --------------------------------------------------------------------
  486. static LONG NEAR ViewerPictureCreate( HWND hwndPicture, LPARAM lParam )
  487.  
  488. {
  489.     NPPICTUREDATA      pPictureData;                    // Temp -> to picture data struct
  490.     HPICTUREDATA       hPictureData;                    // Handle to picture data struct
  491.     LPMDICREATESTRUCT  lpmdicreate;                     // MDI create struct
  492.     struct _stat       statbuf;                         // File statictics struct
  493.     char               szBuffer[MAX_PATH_LEN];          // Temp buffer
  494.     DWORD              dwBytes;                         // File size
  495.     OSErr              oserr;                           // Error return
  496.     WORD               wIDString1;                      // Resource string id
  497.     WORD               wIDString2;                      // Resource string id
  498.     POINT              ptCorner;                        // Upper Left corner of pict wnd
  499.     RECT               rcWindow;                        // Window rect
  500.     int                nDiff;                           // Temp
  501.     RECT               rcclientClient;                  // Client rect of MDI client wnd
  502.     WORD               wWidth;                          // Width of window
  503.     WORD               wHeight;                         // Height of window
  504.     WNDENUMPROC        lpfnEnumPictures;                // -> to enumeration proc
  505.     LPSTR              lpName;                          // Temp -> picture name
  506.     PicFile            picPicFile;                      // Picture file handle
  507.     HDC                hdc;                             // Window hdc
  508.     HCURSOR            hcursorSave;                     // Prior cursor
  509.     char               szCompressor[sizeof(DWORD) + 1]; // compressor type
  510.     QTOLE_OPENWND      qtoleOpenWnd;                    // Ole open wnd struct
  511.     LPQTOLE_OLEDATA    lpOleData;                       // -> ole data
  512.     WORD               wZoomIndex;                      // Initial zoom index
  513.  
  514.  
  515.     pPictureData = (NPPICTUREDATA) NULL;
  516.     szBuffer[0] = '\0';
  517.     hcursorSave = NULL;
  518.  
  519.     if( !(hPictureData = (HPICTUREDATA)
  520.         LocalAlloc( LPTR, sizeof( PICTUREDATASTRUCT )))) {
  521.         CommonTellUser( ViewerQueryResources(),
  522.             VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  523.         goto Failed;
  524.     }
  525.     pPictureData = (NPPICTUREDATA) LocalLock( hPictureData );
  526.     SetWindowWord( hwndPicture, 0, (WORD) pPictureData );
  527.  
  528.     // mdi struct filled before call to MDI create in LaunchPictureWnd
  529.     lpmdicreate = (LPMDICREATESTRUCT)
  530.         ((LPCREATESTRUCT) lParam)->lpCreateParams;
  531.  
  532.     lstrcpy( pPictureData->szPictureName, (LPSTR) lpmdicreate->szTitle );
  533.  
  534.     // Strip off and save extension so that name fits better
  535.     // on title bar of window
  536.     pPictureData->szPictureExt[0] = '\0';
  537.     lpName = pPictureData->szPictureName;
  538.     while( *lpName ) {
  539.         if( *lpName == '.' ) {
  540.             lstrcpy( pPictureData->szPictureExt, lpName );
  541.             *lpName = '\0';
  542.             SetWindowText( hwndPicture, pPictureData->szPictureName );
  543.             break;
  544.         }
  545.         else
  546.             lpName = AnsiNext( lpName );
  547.     }
  548.  
  549.     // Open picture file and extract picture
  550.     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  551.     // Cache path
  552.     lstrcpy( pPictureData->szPicturePath, (LPSTR) lpmdicreate->lParam );
  553.     if( OpenPictureFile( pPictureData->szPicturePath,
  554.         &picPicFile, OF_READ )) {
  555.         CommonTellUser( ViewerQueryResources(),
  556.             VIEWER_STRING_NOOPENFILE, VIEWER_STRING_CAPTION,
  557.             MB_OK, (LPSTR) lpmdicreate->szTitle );
  558.         goto Failed;
  559.     }
  560.  
  561.     pPictureData->phPicture = GetPictureFromFile( picPicFile );
  562.     ClosePictureFile( picPicFile );
  563.  
  564.     if( !pPictureData->phPicture ) {
  565.         if( ( oserr = GetMoviesStickyError()) == noPictureInFile )
  566.             wIDString1 = VIEWER_STRING_NOPICINFILE;
  567.         else if( oserr == insufficientMemory )
  568.             wIDString1 = VIEWER_STRING_NOMEMORY;
  569.         else
  570.             wIDString1 = VIEWER_STRING_NOGETPIC;
  571.  
  572.         ClearMoviesStickyError();
  573.  
  574.         CommonTellUser( ViewerQueryResources(),
  575.             wIDString1, VIEWER_STRING_CAPTION,
  576.             MB_OK, (LPSTR) lpmdicreate->szTitle );
  577.         goto Failed;
  578.     }
  579.  
  580.     // Check for duplicates. Fix up titles if necessary
  581.     // Initialize globals used during enumeration
  582.     g.wPictureCount = 1;
  583.     g.bCreating =  TRUE;
  584.     if( ( ViewerQueryNumPictures() > 0 ) &&
  585.         ( lpfnEnumPictures = (WNDENUMPROC) MakeProcInstance
  586.         ( (FARPROC) CheckDupEnumProc, ViewerQueryInstance()))) {
  587.         EnumChildWindows( ViewerQueryClientWindow(),
  588.             lpfnEnumPictures, MAKELPARAM( hwndPicture, 0 ));
  589.         FreeProcInstance( (FARPROC) lpfnEnumPictures );
  590.  
  591.         // Fix up title if duplicate
  592.         // Title of 1st dup is fixed up during enum
  593.         if( g.wPictureCount > 1 ) {
  594.             pPictureData->wDuplicationIndex = g.wPictureCount;
  595.             wsprintf( szBuffer, "%s:%u",
  596.                 (LPSTR) pPictureData->szPictureName,
  597.                 pPictureData->wDuplicationIndex );
  598.             SetWindowText( hwndPicture, szBuffer );
  599.         }
  600.     }
  601.  
  602.     // Get the palette for the picture if the monitor is palettized
  603.     // A default palette is returned if the picture does not have a palette
  604.     pPictureData->hpalPicture = NULL;
  605.     if( ViewerIsPalettized() && ( hdc = GetDC( hwndPicture ))) {
  606.         pPictureData->hpalPicture =
  607.             GetPicturePalette( pPictureData->phPicture );
  608.         ReleaseDC( hwndPicture, hdc );
  609.     }
  610.  
  611.  
  612.     // Get file size  Note: Need to switch to OEM char set.
  613.     // Sizes are displayed in banner bar and in info dialog
  614.     AnsiToOem( pPictureData->szPicturePath, szBuffer );
  615.     if( (_stat( szBuffer, &statbuf )) == 0 ) {
  616.         if( statbuf.st_size < 1000L ) {
  617.             dwBytes = (DWORD) statbuf.st_size;
  618.             wIDString1 = VIEWER_STRING_SIZEBYTES;
  619.             wIDString2 = VIEWER_STRING_SIZEBYTESONDISK;
  620.         }
  621.         else {
  622.             dwBytes =  (DWORD) ( statbuf.st_size / 1000L );
  623.             wIDString1 = VIEWER_STRING_SIZEKBYTES;
  624.             wIDString2 = VIEWER_STRING_SIZEKBYTESONDISK;
  625.         }
  626.  
  627.         LoadString( ViewerQueryResources(),
  628.             wIDString1, szBuffer, sizeof( szBuffer ));
  629.         wsprintf( pPictureData->szFileSize, szBuffer, dwBytes );
  630.         LoadString( ViewerQueryResources(),
  631.             wIDString2, szBuffer, sizeof( szBuffer ));
  632.         wsprintf( pPictureData->szFileSizeOnDisk, szBuffer, dwBytes );
  633.     }
  634.  
  635.  
  636.     pPictureData->idImageInfo.idSize = sizeof( ImageDescription );
  637.     if( GetPictureInfo( pPictureData->phPicture, &pPictureData->idImageInfo )) {
  638.         CommonTellUser( ViewerQueryResources(),
  639.             VIEWER_STRING_NOINFO, VIEWER_STRING_CAPTION, MB_OK );
  640.         goto Failed;
  641.     }
  642.  
  643.     // Picture type
  644.     if( pPictureData->idImageInfo.name[0] ) {
  645.         lstrcpy( pPictureData->szPictType, pPictureData->idImageInfo.name );
  646.     }
  647.     else { // Compressor type is stored as a DWORD. i.e. 'jpeg'
  648.         if( pPictureData->idImageInfo.CodecType ) {
  649.             *((PDWORD) &szCompressor) = pPictureData->idImageInfo.CodecType;
  650.             szCompressor[ sizeof(DWORD) ] = '\0';
  651.         }
  652.  
  653.         pPictureData->szPictType[0] = '\0';
  654.         // Spaces in "raw ", "rle " etc are necessary !!!
  655.         if( !pPictureData->idImageInfo.CodecType ||
  656.             !lstrcmpi( szCompressor, "raw " ))
  657.             wIDString1 = VIEWER_STRING_CODEC_NONE;
  658.         else if( !lstrcmpi( szCompressor, "jpeg" ))
  659.             wIDString1 = VIEWER_STRING_CODEC_PHOTO;
  660.         else if( !lstrcmpi( szCompressor, "rle " ))
  661.             wIDString1 = VIEWER_STRING_CODEC_ANIMATION;
  662.         else if( !lstrcmpi( szCompressor, "smc " ))
  663.             wIDString1 = VIEWER_STRING_CODEC_GRAPHICS;
  664.         else if( !lstrcmpi( szCompressor, "rpza" ))
  665.             wIDString1 = VIEWER_STRING_CODEC_VIDEO;
  666.         else if( !lstrcmpi( szCompressor, "cvid" ))
  667.             wIDString1 = VIEWER_STRING_CODEC_CVID;
  668.         else
  669.             wIDString1 = VIEWER_STRING_CODEC_NONE;
  670.  
  671.         LoadString( ViewerQueryResources(), wIDString1,
  672.             pPictureData->szPictType, sizeof( pPictureData->szPictType ));
  673.     }
  674.  
  675.     // Adjust resolution for Mac wierdness
  676.     if( ( pPictureData->idImageInfo.hRes == -1 ) &&
  677.         ( pPictureData->idImageInfo.vRes == -1 ))
  678.         pPictureData->idImageInfo.hRes =
  679.         pPictureData->idImageInfo.vRes = MAKELFIXED( 72, 0 );
  680.     else if( pPictureData->idImageInfo.hRes == -1 )
  681.         pPictureData->idImageInfo.hRes = pPictureData->idImageInfo.vRes;
  682.     else if( pPictureData->idImageInfo.vRes == -1 )
  683.         pPictureData->idImageInfo.vRes = pPictureData->idImageInfo.hRes;
  684.  
  685.     // Initialize this to something impossible so that
  686.     // size checking tests in ZoomPicture, etc will work
  687.     // during startup
  688.     pPictureData->zsZoomScroll.wCurZoomIndex = IMAGE_SIZE_FIRST - 1;
  689.  
  690.     // Create the picture window controls
  691.     if( CreateViewerKids( hwndPicture, pPictureData ))
  692.         goto Failed; // Errors reported by function
  693.  
  694.     pPictureData->spmsHScroll.wCurPos = 0;
  695.     pPictureData->spmsVScroll.wCurPos = 0;
  696.  
  697.     // Set copy option default values
  698.     SetOptionsDefaults( hwndPicture, pPictureData );
  699.  
  700.     if( pPictureData->qtoleOptions.bZoomHalf )
  701.         wZoomIndex = IMAGE_SIZE_50;
  702.     else if( pPictureData->qtoleOptions.bZoomDouble )
  703.         wZoomIndex = IMAGE_SIZE_200;
  704.     else
  705.         wZoomIndex = IMAGE_SIZE_100;
  706.  
  707.     // Build picture. This initializes pPictureData->rcCurPictureRect.
  708.     if( ZoomPicture( hwndPicture, wZoomIndex ))
  709.         goto Failed; // Error displayed by function
  710.  
  711.     // At this point, the picture is in a window whose size
  712.     // and position is the current MDI default . Now, resize to actual
  713.     // size of picture, without clipping if possible
  714.  
  715.     // Get default corner
  716.     GetWindowRect( hwndPicture, &rcWindow );
  717.     MapWindowPoints( HWND_DESKTOP, ViewerQueryClientWindow(),
  718.         (LPPOINT) &rcWindow, 2 );
  719.     ptCorner = *((LPPOINT) &rcWindow.left);
  720.  
  721.     // Adjust window to fit normal size of picture
  722.     rcWindow = pPictureData->rcCurPictureRect;
  723.     // get client rect from picture rect in client coordinates
  724.     ClientRectFromPicture( &rcWindow );
  725.     // Now adjust for windows stuff
  726.     AdjustWindowRect( &rcWindow,
  727.         GetWindowLong( hwndPicture, GWL_STYLE ), FALSE );
  728.     wWidth  = rcWindow.right  - rcWindow.left;
  729.     wHeight = rcWindow.bottom - rcWindow.top;
  730.     OffsetRect( &rcWindow, ptCorner.x - rcWindow.left,
  731.         ptCorner.y - rcWindow.top );
  732.     // rcWindow now contains the resized window positioned so that
  733.     // the UL corner is at the MDI default position
  734.  
  735.     // Now see if it will fit on screen.
  736.     GetClientRect( ViewerQueryClientWindow(), &rcclientClient );
  737.     if( rcWindow.right > rcclientClient.right ) { // extends beyond right border
  738.                                                   // Try to shift it to the left
  739.         nDiff = rcclientClient.right - wWidth;
  740.         rcWindow.left  = max( 0, nDiff );
  741.         rcWindow.right = rcclientClient.right;
  742.     }
  743.  
  744.     if( rcWindow.bottom > rcclientClient.bottom ) { // extends beyond bottom
  745.                                                     // Try to shift it up
  746.         nDiff = rcclientClient.bottom - wHeight;
  747.         rcWindow.top    = max( 0, nDiff );
  748.         rcWindow.bottom = rcclientClient.bottom;
  749.     }
  750.  
  751.     MoveWindow( hwndPicture, rcWindow.left, rcWindow.top,
  752.         rcWindow.right - rcWindow.left,
  753.         rcWindow.bottom - rcWindow.top, TRUE );
  754.  
  755.     SetCursor( hcursorSave );
  756.  
  757.     SetFocus( hwndPicture );
  758.  
  759.     // Tell qtole.dll that the picture wnd has been opened
  760.     if( ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer ) {
  761.         qtoleOpenWnd.lStructSize  = sizeof( qtoleOpenWnd );
  762.         qtoleOpenWnd.lVersion     = VERSION_1;
  763.         qtoleOpenWnd.wObjectType  = PICTURE_OBJECT;
  764.         qtoleOpenWnd.hwndObject   = hwndPicture;
  765.         qtoleOpenWnd.lpObjectPath = pPictureData->szPicturePath;
  766.         qtoleOpenWnd.lpObjectName = pPictureData->szPictureName;
  767.  
  768.         QTOLE_OpeningNewObjectWnd( lpOleData, &qtoleOpenWnd );
  769.     }
  770.  
  771.     return  0L;
  772.  
  773.  Failed:
  774.     if( hcursorSave )
  775.         SetCursor( hcursorSave );
  776.  
  777.     if( pPictureData->phPicture != NULL)
  778.         DisposePicture( pPictureData->phPicture );
  779.  
  780.     if( pPictureData->hpalPicture )
  781.         DeleteObject( pPictureData->hpalPicture );
  782.  
  783.     SetWindowWord( hwndPicture, 0, 0 );
  784.  
  785.     if( pPictureData )
  786.         LocalUnlock( hPictureData );
  787.     if( hPictureData )
  788.         LocalFree( hPictureData );
  789.  
  790.     return -1;
  791.  
  792. }
  793.  
  794.  
  795. // Function: CheckDupEnumProc - Checks for duplicate pictures and
  796. //                              fixes up titles if there are any
  797. // --------------------------------------------------------------------
  798. // Parameters: As required by Microsoft Windows
  799. //
  800. // Returns:    Always TRUE;
  801. // --------------------------------------------------------------------
  802. BOOL __export CALLBACK CheckDupEnumProc( HWND hwnd, LPARAM lParam )
  803.  
  804. // Look for duplicate pictures. Test is on path rather than just name
  805.  
  806. {
  807.     char             szBuffer[50];       // Temp buffer
  808.     HWND             hwndActivePicture;  // Handle of active picture wnd
  809.     NPPICTUREDATA    pPictureData;       // -> enum wnd picture data struct
  810.     NPPICTUREDATA    pActivePictureData; // -> active wnd picture data struct
  811.  
  812.  
  813.     // skip active picture
  814.     if( ( hwndActivePicture = (HWND) LOWORD( lParam )) == hwnd )
  815.         return TRUE;
  816.  
  817.     if( !GetClassName( hwnd, szBuffer, sizeof( szBuffer )) ||
  818.         lstrcmpi( szBuffer, VIEWER_PICTURE_CLASS ))
  819.         return TRUE;
  820.  
  821.     pPictureData = (NPPICTUREDATA) GetWindowWord( hwnd, 0 );
  822.     pActivePictureData =
  823.         (NPPICTUREDATA) GetWindowWord( hwndActivePicture, 0 );
  824.     if( !pPictureData || !pActivePictureData )
  825.         return TRUE;
  826.  
  827.     if( !lstrcmpi( pPictureData->szPicturePath,
  828.         pActivePictureData->szPicturePath )) { // Found a duplicate
  829.         g.wPictureCount++;
  830.         if( g.bCreating ) {
  831.             if( pPictureData->wDuplicationIndex == 0 ) {
  832.                 pPictureData->wDuplicationIndex = 1;
  833.                 wsprintf( szBuffer, "%s:%u",
  834.                     (LPSTR) pPictureData->szPictureName,
  835.                     pPictureData->wDuplicationIndex );
  836.                 SetWindowText( hwnd, szBuffer );
  837.             }
  838.         }
  839.         else {
  840.             if( pPictureData->wDuplicationIndex >
  841.                 pActivePictureData->wDuplicationIndex ) {
  842.                 pPictureData->wDuplicationIndex--;
  843.                 wsprintf( szBuffer, "%s:%u",
  844.                     (LPSTR) pPictureData->szPictureName,
  845.                     pPictureData->wDuplicationIndex );
  846.                 SetWindowText( hwnd, szBuffer );
  847.             }
  848.             if( pPictureData->wDuplicationIndex == 1 )
  849.                 g.hwndFirstDup = hwnd;
  850.         }
  851.  
  852.         if( pPictureData->hwndGetInfo &&
  853.             !PostMessage( pPictureData->hwndGetInfo,
  854.             WM_INFO_UPDATEFILENAME, 0, 0L ))
  855.             SendMessage( pPictureData->hwndGetInfo,
  856.             WM_INFO_UPDATEFILENAME, 0, 0L );
  857.     }
  858.  
  859.     return TRUE;
  860. }
  861.  
  862.  
  863. // Function: ViewerEditCommands - Process WM_COMMAND, Edit popup messages
  864. // --------------------------------------------------------------------
  865. // Parameters: HWND   hwndPicture;    Picture window
  866. //             WORD   wIDItem;        Menu id
  867. //             WORD   wNotifyCode;    notification message
  868. //
  869. // Returns:    LONG   generally 0L
  870. // --------------------------------------------------------------------
  871. static LONG NEAR ViewerEditCommands
  872.                    (HWND hwndPicture, WPARAM wIDItem, WORD wNotifyCode )
  873.  
  874. {
  875.     NPPICTUREDATA  pPictureData; // -> picture data struct
  876.     HDC            hdc;          // Handle to device context
  877.     HDC            hdcMem;       // Handle to mem device context
  878.     RECT           rcPicture;    // Picture rect
  879.     HBITMAP        hBitmap;      // Handle to bitmap passed to clipboard
  880.     HBITMAP        hSaveBitmap1; // Temp bitmap handle
  881.     HCURSOR        hcursorSave;  // Saved cursor
  882.     HBRUSH         hbrushSave;   // Prev brush
  883.     DIBHandle      hbmpDIB;      // Handle of DIB bitmap passed to clipboard
  884.     OSErr          oserr;        // Error return from DrawPictureFile
  885.     HPALETTE       hpal;         // Palette handle
  886.     LPQTOLE_OLEDATA  lpOleData;  // -> ole data
  887.     HPALETTE       hpalSave;     // Prev palette
  888.  
  889.  
  890.     if( !( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  891.         CommonTellUser( ViewerQueryResources(),
  892.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  893.         return 0L;
  894.     }
  895.  
  896.     switch( wIDItem ) {
  897.         case VIEWER_EDIT_COPYPICTURE:
  898.             if( IsIconic( hwndPicture ))
  899.                 return 0L;
  900.  
  901.             // If ole, let ole do the copy
  902.             if( ( lpOleData = ViewerQueryOleData()) && lpOleData->lpqtoleServer ) {
  903.                 PopulateOptionsStruct( hwndPicture, pPictureData );
  904.  
  905.                 QTOLE_Copy( lpOleData, (LPQTOLE_OPTIONS) &pPictureData->qtoleOptions );
  906.  
  907.                 // We must compensate for an error in certain drivers by
  908.                 // resetting the palette back the way we found it
  909.                 if( ViewerIsPalettized() &&
  910.                     pPictureData->hpalPicture && ( hdc = GetDC( hwndPicture ))) {
  911.                     hpalSave = SelectPalette( hdc, pPictureData->hpalPicture, 0 );
  912.                     RealizePalette( hdc );
  913.  
  914.                     SelectPalette( hdc, hpalSave, 0 );
  915.                     ReleaseDC( hwndPicture, hdc );
  916.                 }
  917.             }
  918.             else // No ole so do copy here
  919.             {
  920.                 if( !( hdc = GetDC( hwndPicture ))) {
  921.                     CommonTellUser( ViewerQueryResources(),
  922.                         VIEWER_STRING_NODC,
  923.                         VIEWER_STRING_CAPTION, MB_OK );
  924.                     return 0L;
  925.                 }
  926.  
  927.                 rcPicture.left = rcPicture.top = 0;
  928.                 rcPicture.right  = pPictureData->idImageInfo.width;
  929.                 rcPicture.bottom = pPictureData->idImageInfo.height;
  930.  
  931.                 if( !( hBitmap = CreateCompatibleBitmap
  932.                     ( hdc, rcPicture.right, rcPicture.bottom ))) {
  933.                     CommonTellUser( ViewerQueryResources(),
  934.                         VIEWER_STRING_COPYFAILED,
  935.                         VIEWER_STRING_CAPTION, MB_OK );
  936.                     ReleaseDC( hwndPicture, hdc );
  937.                     return 0L;
  938.                 }
  939.  
  940.                 oserr = 1L; // initialize to nonzero value
  941.                 if( (hdcMem = CreateCompatibleDC( hdc )) &&
  942.                     ( hSaveBitmap1 = SelectObject( hdcMem, hBitmap ))) {
  943.                     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  944.                     hbrushSave = SelectObject( hdcMem, PICBACKGRNDBRUSH );
  945.                     oserr = DrawPicture( hdcMem, pPictureData->phPicture,
  946.                         &rcPicture, NULL );
  947.                     SetCursor( hcursorSave );
  948.  
  949.                     // Unselect the bitmap and brush
  950.                     SelectObject( hdcMem, hSaveBitmap1 );
  951.                     if( hbrushSave )
  952.                         SelectObject( hdcMem, hbrushSave );
  953.  
  954.                     if( !oserr ) {
  955.                         OpenClipboard( hwndPicture );
  956.                         EmptyClipboard();
  957.                         // Give bitmap to clipboard if OK
  958.                         if( !SetClipboardData( CF_BITMAP, hBitmap ))
  959.                             DeleteObject( hBitmap );
  960.  
  961.                         // Now add palette if there is one
  962.                         if( ( hpal = GetPicturePalette( pPictureData->phPicture )) &&
  963.                             !SetClipboardData( CF_PALETTE, hpal ))
  964.                             DeleteObject( hpal );
  965.  
  966.                         // Now try to add DIBitmap to clipboard
  967.                         if( ( hbmpDIB =
  968.                             PictureToDIB( pPictureData->phPicture )) &&
  969.                             !SetClipboardData( CF_DIB, hbmpDIB ))
  970.                             GlobalFree( hbmpDIB );
  971.  
  972.                         CloseClipboard();
  973.                     }
  974.                 }
  975.                 else {
  976.                     if( hBitmap )
  977.                         DeleteObject( hBitmap );
  978.                 }
  979.  
  980.                 if( oserr )
  981.                     CommonTellUser( ViewerQueryResources(),
  982.                     VIEWER_STRING_DRAWPICFAIL,
  983.                     VIEWER_STRING_CAPTION, MB_OK );
  984.                 if( hdcMem )
  985.                     DeleteDC( hdcMem );
  986.  
  987.                 ReleaseDC( hwndPicture, hdc );
  988.             }
  989.  
  990.             return 0L;
  991.  
  992.         case VIEWER_EDIT_OPTIONS:
  993.             PopulateOptionsStruct( hwndPicture, pPictureData );
  994.  
  995.             if( ViewerGetOptions( hwndPicture, &pPictureData->qtoleOptions ))
  996.                 UpdatePictForOptions( hwndPicture, pPictureData, FALSE );
  997.  
  998.             return 0L;
  999.  
  1000.         case VIEWER_EDIT_CANCELSEL:
  1001.             if( !IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ) &&
  1002.                 ( hdc = GetDC( hwndPicture ))) {
  1003.                 DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1004.                 ReleaseDC( hwndPicture, hdc );
  1005.                 SetRectEmpty( &pPictureData->qtoleOptions.rcSelection );
  1006.             }
  1007.  
  1008.             return 0L;
  1009.     }
  1010.  
  1011.     return 0L; // should never get here
  1012.  
  1013. }
  1014.  
  1015.  
  1016. // Function: InitSelection - Initiates the selection
  1017. // --------------------------------------------------------------------
  1018. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1019. //             POINT         ptCursor         Cursor position
  1020. //
  1021. // Returns:    BOOL          TRUE if OK
  1022. // --------------------------------------------------------------------
  1023. static BOOL NEAR InitSelection( HWND hwndPicture, POINT ptCursor )
  1024.  
  1025. {
  1026.     NPPICTUREDATA     pPictureData;
  1027.     HDC               hdc;
  1028.  
  1029.     // First remove old selection
  1030.     if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) {
  1031.         g.rcSelection = pPictureData->qtoleOptions.rcSelection;
  1032.         if( !IsRectEmpty( &g.rcSelection ) &&
  1033.             ( hdc = GetDC( hwndPicture ))) {
  1034.             DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1035.             ReleaseDC( hwndPicture, hdc );
  1036.         }
  1037.     }
  1038.  
  1039.     if( hdc = GetDC( NULL )) {
  1040.         ClientToScreen( hwndPicture, &ptCursor );
  1041.  
  1042.         *(LPPOINT) &g.rcSelection.left  = ptCursor;
  1043.         *(LPPOINT) &g.rcSelection.right = ptCursor;
  1044.  
  1045.         DrawFocusRect( hdc, &g.rcSelection );
  1046.  
  1047.         ReleaseDC( NULL, hdc );
  1048.  
  1049.         return TRUE;
  1050.     }
  1051.  
  1052.     return FALSE;
  1053. }
  1054.  
  1055. // Function: MoveTheSelectRect - Move the selection rect
  1056. // --------------------------------------------------------------------
  1057. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1058. //             POINT         ptCursor         Cursor position
  1059. //
  1060. // Returns:    VOID
  1061. // --------------------------------------------------------------------
  1062. static VOID NEAR MoveTheSelectRect( HWND hwndPicture, POINT ptCursor )
  1063.  
  1064. {
  1065.     HDC       hdc;
  1066.  
  1067.     if( hdc = GetDC( NULL )) {
  1068.         ClientToScreen( hwndPicture, &ptCursor );
  1069.         DrawFocusRect( hdc, &g.rcSelection );
  1070.  
  1071.         *(LPPOINT) &g.rcSelection.right = ptCursor;
  1072.         if( g.rcSelection.right < g.rcSelection.left )
  1073.             g.rcSelection.right = g.rcSelection.left;
  1074.  
  1075.         if( g.rcSelection.bottom < g.rcSelection.top )
  1076.             g.rcSelection.bottom = g.rcSelection.top;
  1077.  
  1078.         DrawFocusRect( hdc, &g.rcSelection );
  1079.  
  1080.         ReleaseDC( NULL, hdc );
  1081.     }
  1082.  
  1083.     return;
  1084. }
  1085.  
  1086. // Function: EndTheSelection - End the selection
  1087. // --------------------------------------------------------------------
  1088. // Parameters: HWND          hwndPicture      Handle of picture wnd
  1089. //
  1090. // Returns:    VOID
  1091. // --------------------------------------------------------------------
  1092. static VOID NEAR EndTheSelection( HWND hwndPicture )
  1093.  
  1094. {
  1095.     NPPICTUREDATA     pPictureData;
  1096.     int               nZoomMult;
  1097.     HDC               hdc;
  1098.  
  1099.     // Remove selection rect here and redraw later using function
  1100.     // This is necessary because roundoff in convertions can cause
  1101.     // one pixel differences in rect coordinates
  1102.     if( hdc = GetDC( NULL )) {
  1103.         DrawFocusRect( hdc, &g.rcSelection );
  1104.         ReleaseDC( NULL, hdc );
  1105.     }
  1106.  
  1107.     if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 )) {
  1108.         if( !IsRectEmpty( &g.rcSelection )) {
  1109.             MapWindowPoints( HWND_DESKTOP, hwndPicture,
  1110.                 (LPPOINT) &g.rcSelection, 2 );
  1111.  
  1112.             ClientToPicture( (LPPOINT) &g.rcSelection, 2 );
  1113.             // rcCurPictureRect knows about scroll offsets.
  1114.             // These offsets are negative
  1115.             OffsetRect( &g.rcSelection,
  1116.                 -pPictureData->rcCurPictureRect.left,
  1117.                 -pPictureData->rcCurPictureRect.top );
  1118.  
  1119.             // Now convert to 100% zoom.  rcSelection will be stored
  1120.             // at 100% zoom. Copy will reflect actual zoom
  1121.             nZoomMult = (int) ViewerQueryZoomMultiplier
  1122.                 ( pPictureData->zsZoomScroll.wCurZoomIndex );
  1123.             g.rcSelection.left   = MulDiv( g.rcSelection.left,   100, nZoomMult );
  1124.             g.rcSelection.top    = MulDiv( g.rcSelection.top,    100, nZoomMult );
  1125.             g.rcSelection.right  = MulDiv( g.rcSelection.right,  100, nZoomMult );
  1126.             g.rcSelection.bottom = MulDiv( g.rcSelection.bottom, 100, nZoomMult );
  1127.  
  1128.             // Now check that section is inside picture
  1129.             if( g.rcSelection.left < 0 )
  1130.                 g.rcSelection.left = 0;
  1131.             if( g.rcSelection.top < 0 )
  1132.                 g.rcSelection.top = 0;
  1133.             if( g.rcSelection.right > (int) pPictureData->idImageInfo.width )
  1134.                 g.rcSelection.right = pPictureData->idImageInfo.width;
  1135.             if( g.rcSelection.bottom > (int) pPictureData->idImageInfo.height )
  1136.                 g.rcSelection.bottom = pPictureData->idImageInfo.height;
  1137.             // g.rcSelection now has selection relative to UL corner
  1138.             // of picture at 100% zoom
  1139.         }
  1140.  
  1141.         pPictureData->qtoleOptions.rcSelection = g.rcSelection;
  1142.  
  1143.         // Now redraw the rect to leave it visible
  1144.         if( hdc = GetDC( hwndPicture )) {
  1145.             DrawSelectionRect( hwndPicture, hdc, pPictureData );
  1146.             ReleaseDC( hwndPicture, hdc );
  1147.         }
  1148.     }
  1149.  
  1150.  
  1151.     return;
  1152. }
  1153.  
  1154.  
  1155. // Function: ViewerImageCommands - Process WM_COMMAND, Image popup messages
  1156. // --------------------------------------------------------------------
  1157. // Parameters: HWND   hwndPicture;    Picture window
  1158. //             WORD   wIDItem;        Menu id
  1159. //             WORD   wNotifyCode;    notification message
  1160. //
  1161. // Returns:    LONG   generally 0L
  1162. // --------------------------------------------------------------------
  1163. static LONG NEAR ViewerImageCommands
  1164.                    (HWND hwndPicture, WPARAM wIDItem, WORD wNotifyCode )
  1165.  
  1166. {
  1167.     DLGPROC        lpDlgProc;    // -> dlg callback proc
  1168.     HWND           hInfoDialog;  // Handle to modeless info dialog
  1169.     NPPICTUREDATA  pPictureData; // -> picture data struct
  1170.  
  1171.     if( !(pPictureData =
  1172.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  1173.         CommonTellUser( ViewerQueryResources(),
  1174.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  1175.         return 0L;
  1176.     }
  1177.  
  1178.     switch( wIDItem ) {
  1179.         case VIEWER_IMAGE_GETINFO:
  1180.             if( pPictureData->hwndGetInfo ) {
  1181.                 SetFocus( pPictureData->hwndGetInfo );
  1182.             }
  1183.             else if( !(lpDlgProc = (DLGPROC) MakeProcInstance
  1184.                 ( (FARPROC) GetInfoDlgProc, ViewerQueryInstance())) ||
  1185.                 !( hInfoDialog = CreateDialog( ViewerQueryResources(),
  1186.                 MAKEINTRESOURCE( VIEWER_DLG_GETINFO ),
  1187.                 ViewerQueryFrameWindow(), lpDlgProc ))) {
  1188.                 CommonTellUser( ViewerQueryResources(),
  1189.                     VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1190.             }
  1191.  
  1192.             return 0L;
  1193.  
  1194.         case VIEWER_IMAGE_HALFSIZE:
  1195.         case VIEWER_IMAGE_NORMALSIZE:
  1196.         case VIEWER_IMAGE_DOUBLESIZE:
  1197.             // errors reported by function
  1198.             ZoomPicture( hwndPicture, wIDItem );
  1199.             return 0L;
  1200.     }
  1201.  
  1202.     return 0L; // should never get here
  1203.  
  1204. }
  1205.  
  1206.  
  1207. // Function: PaintThePicture - processes the WM_PAINT message when normal
  1208. // --------------------------------------------------------------------
  1209. // Parameters: HWND         hwndPicture     Handle of Picture window
  1210. //
  1211. // Returns:    LONG         0L if successful
  1212. // --------------------------------------------------------------------
  1213. static LONG NEAR PaintThePicture( HWND hwndPicture )
  1214.  
  1215. {
  1216.     PAINTSTRUCT     ps;              // Paint struct
  1217.     NPPICTUREDATA   pPictureData;    // -> picture data struct
  1218.     HCURSOR         hcursorSave;     // Save cursor handle
  1219.     HBRUSH          hbrushSave;      // Prev brush
  1220.     RECT            rcclientPicture; // Picture rect in client coordinates
  1221.     int             nRegion;         // Return from IntersectClipRegion
  1222.     OSErr           oserr;           // DrawPicture error return
  1223.     WORD            wIDError;        // Error message ID
  1224.  
  1225.  
  1226.     if( !( pPictureData =
  1227.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  1228.         if( BeginPaint( hwndPicture, &ps ))
  1229.             EndPaint( hwndPicture, &ps );
  1230.         return 0L;
  1231.     }
  1232.  
  1233.     // Always paint the grow box. This must come before BeginPaint
  1234.     InvalidateRect( hwndPicture, &pPictureData->rcGrowBox, FALSE );
  1235.  
  1236.     if( !BeginPaint( hwndPicture, &ps )) {
  1237.         CommonTellUser( ViewerQueryResources(),
  1238.             VIEWER_STRING_NOMEMORY,
  1239.             VIEWER_STRING_CAPTION, MB_OK );
  1240.         return VIEWER_STRING_NOMEMORY;
  1241.     }
  1242.  
  1243.     // First draw the grow box and exclude the rect so that picture isn't
  1244.     // draw over it below
  1245.     PaintTheGrowBox( hwndPicture, ps.hdc, pPictureData );
  1246.     ExcludeClipRect( ps.hdc, pPictureData->rcGrowBox.left,
  1247.         pPictureData->rcGrowBox.top,
  1248.         pPictureData->rcGrowBox.right,
  1249.         pPictureData->rcGrowBox.bottom );
  1250.  
  1251.     // Note: rcCurPictureRect knows about scrolling offset. left and
  1252.     // top are negative if pict is scrolled. (0,0) is always the UL
  1253.     // corner of the displayed portion of the picture in picture
  1254.     // coordinates.
  1255.  
  1256.     rcclientPicture = pPictureData->rcCurPictureRect;
  1257.  
  1258.     // Convert to client coordinates since ps.hdc understands client
  1259.     // coordinates
  1260.     PictureToClient( (LPPOINT) &rcclientPicture, 2 );
  1261.  
  1262.     // Paint the background
  1263.     hbrushSave = SelectObject( ps.hdc, PICBACKGRNDBRUSH );
  1264.     SaveDC( ps.hdc );
  1265.     ExcludeClipRect( ps.hdc, rcclientPicture.left, rcclientPicture.top,
  1266.         rcclientPicture.right, rcclientPicture.bottom );
  1267.     FillRect( ps.hdc, &ps.rcPaint, PICBACKGRNDBRUSH );
  1268.     RestoreDC( ps.hdc, -1 );
  1269.     if( hbrushSave )
  1270.         SelectObject( ps.hdc, hbrushSave );
  1271.  
  1272.     // Check if picture needs to be painted
  1273.     SaveDC( ps.hdc );
  1274.     nRegion = IntersectClipRect( ps.hdc,
  1275.         rcclientPicture.left, rcclientPicture.top,
  1276.         rcclientPicture.right, rcclientPicture.bottom );
  1277.     if( ( nRegion == ERROR ) || ( nRegion == NULLREGION )) {
  1278.         RestoreDC( ps.hdc, -1 );
  1279.         EndPaint( hwndPicture, &ps );
  1280.         return 0L;
  1281.     }
  1282.  
  1283.     // Draw picture
  1284.     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1285.  
  1286.     if( oserr = DrawPicture( ps.hdc, pPictureData->phPicture,
  1287.         &rcclientPicture, NULL )) {
  1288.         if( oserr == insufficientMemory )
  1289.             wIDError = VIEWER_STRING_NOMEMORY;
  1290.         else
  1291.             wIDError = VIEWER_STRING_DRAWPICFAIL;
  1292.  
  1293.         CommonTellUser( ViewerQueryResources(), wIDError,
  1294.             VIEWER_STRING_CAPTION, MB_OK );
  1295.  
  1296.         // Validate rect to prevent infinite loop
  1297.         ValidateRect( hwndPicture, NULL );
  1298.         SetCursor( hcursorSave );
  1299.         RestoreDC( ps.hdc, -1 );
  1300.         EndPaint( hwndPicture, &ps );
  1301.  
  1302.         return VIEWER_STRING_DRAWPICFAIL;
  1303.     }
  1304.     RestoreDC( ps.hdc, -1 );
  1305.  
  1306.     if( !IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ))
  1307.         DrawSelectionRect( hwndPicture, ps.hdc, pPictureData );
  1308.  
  1309.     SetCursor( hcursorSave );
  1310.  
  1311.     // Done painting
  1312.     EndPaint( hwndPicture, &ps );
  1313.  
  1314.     return 0L;
  1315. }
  1316.  
  1317.  
  1318. // Function: DrawSelectionRect - Draws the selection rect
  1319. // --------------------------------------------------------------------
  1320. // Parameters: HWND            hwndPicture    HWND of picture wnd
  1321. //             HDC             hdc            HDC of picture wnd
  1322. //             NPPICTUREDATA   pPictureData
  1323. //
  1324. // Returns:    VOID
  1325. // --------------------------------------------------------------------
  1326. static VOID NEAR DrawSelectionRect
  1327.                 ( HWND hwndPicture, HDC hdc, NPPICTUREDATA pPictureData )
  1328.  
  1329. {
  1330.     RECT       rcSelection;
  1331.     RECT       rcPicture;
  1332.     int        nZoomMult;
  1333.     int        nRegion;
  1334.  
  1335.     // Get picture rect and prevent drawing outside the picture
  1336.     GetClientRect( hwndPicture, &rcPicture );
  1337.     PictureRectFromClient( &rcPicture );
  1338.  
  1339.     nRegion = IntersectClipRect( hdc,
  1340.         rcPicture.left, rcPicture.top,
  1341.         rcPicture.right, rcPicture.bottom );
  1342.     if( ( nRegion == ERROR ) || ( nRegion == NULLREGION ))
  1343.         return;
  1344.  
  1345.     // Convert to current zoom
  1346.     rcSelection = pPictureData->qtoleOptions.rcSelection;
  1347.     nZoomMult = (int) ViewerQueryZoomMultiplier
  1348.         ( pPictureData->zsZoomScroll.wCurZoomIndex );
  1349.     rcSelection.left   = MulDiv( rcSelection.left,   nZoomMult, 100 );
  1350.     rcSelection.top    = MulDiv( rcSelection.top,    nZoomMult, 100 );
  1351.     rcSelection.right  = MulDiv( rcSelection.right,  nZoomMult, 100 );
  1352.     rcSelection.bottom = MulDiv( rcSelection.bottom, nZoomMult, 100 );
  1353.  
  1354.     // Offset for current scroll and convert to client coordinates
  1355.     OffsetRect( &rcSelection,
  1356.         pPictureData->rcCurPictureRect.left,
  1357.         pPictureData->rcCurPictureRect.top );
  1358.     PictureToClient( (LPPOINT) &rcSelection, 2 );
  1359.  
  1360.     DrawFocusRect( hdc, &rcSelection );
  1361.  
  1362.     return;
  1363. }
  1364.  
  1365. // Function: PaintTheIcon - processes the WM_PAINT message when iconic
  1366. // --------------------------------------------------------------------
  1367. // Parameters: HWND         hwndPicture     Handle of Picture window
  1368. //
  1369. // Returns:    LONG         0L
  1370. // --------------------------------------------------------------------
  1371. static LONG NEAR PaintTheIcon( HWND hwndPicture )
  1372.  
  1373. {
  1374.     PAINTSTRUCT        ps;           // Paint struct
  1375.     NPPICTUREDATA      pPictureData; // -> picture data struct
  1376.     HDC                hmemDC;       // Memory DC
  1377.     HBITMAP            hbitmapSave;  // Prev bitmap
  1378.     BITMAP             bm;           // Bitmap struct
  1379.     LPBITMAPINFOHEADER lpbmih;       // -> bitmapinfo header struct
  1380.     HPALETTE           hpalSave;     // Prev palette
  1381.     HBRUSH             hbrush;       // Background brush
  1382.  
  1383.     static RECT        rcPic = {
  1384.                         4, 4, 32, 32}; // Rect used in painting pic
  1385.  
  1386.  
  1387.     InvalidateRect( hwndPicture, NULL, FALSE );
  1388.  
  1389.     if( !BeginPaint( hwndPicture, &ps ))
  1390.         return 0L;
  1391.  
  1392.     if( !( pPictureData = (NPPICTUREDATA)
  1393.         GetWindowWord( hwndPicture, 0 )) ||
  1394.         ( !pPictureData->lpDIBIconMem && !pPictureData->hbitmapIcon )) {
  1395.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1396.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1397.             DeleteObject( hbrush );
  1398.         }
  1399.  
  1400.         if( g.hpictIcon )
  1401.             DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1402.         EndPaint( hwndPicture, &ps );
  1403.         return 0L;
  1404.     }
  1405.  
  1406.     // Will have DIB icon only if palettized
  1407.     if( pPictureData->lpDIBIconMem ) {
  1408.         lpbmih = (LPBITMAPINFOHEADER) pPictureData->lpDIBIconMem;
  1409.  
  1410.         // Select the current system palette into the dc so SetDIBits..
  1411.         // can do color matching. The system palette is set by the last
  1412.         // call to RealizePalette and so the current palette will
  1413.         // match the picture's palette only if the picture is active
  1414.         hpalSave = SelectPalette( ps.hdc, g.hpalCurrentSystem, FALSE );
  1415.  
  1416.         SetDIBitsToDevice( ps.hdc, rcPic.left, rcPic.top,
  1417.             (WORD) lpbmih->biWidth, (WORD) lpbmih->biHeight,
  1418.             0, 0, 0, (WORD) lpbmih->biHeight,
  1419.             (LPVOID) ((LPSTR) lpbmih +
  1420.             (WORD) lpbmih->biSize + SIZE_COLOR_TABLE ),
  1421.             pPictureData->lpDIBIconMem, DIB_RGB_COLORS );
  1422.  
  1423.         if( hpalSave )
  1424.             SelectPalette( ps.hdc, hpalSave, FALSE );
  1425.  
  1426.         // Now paint the background
  1427.         SaveDC( ps.hdc );
  1428.         ExcludeClipRect( ps.hdc, rcPic.left, rcPic.top,
  1429.             rcPic.right, rcPic.bottom );
  1430.         // COLOR_APPWORKSPACE is standard MDI background color
  1431.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1432.             FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1433.             DeleteObject( hbrush );
  1434.         }
  1435.         RestoreDC( ps.hdc, -1 );
  1436.  
  1437.         // Now draw the picture frame
  1438.         if( g.hpictIcon )
  1439.             DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1440.     }
  1441.     else {
  1442.         hmemDC = NULL;
  1443.         if( pPictureData->hbitmapIcon &&
  1444.             ( hmemDC = CreateCompatibleDC( ps.hdc )) &&
  1445.             ( hbitmapSave =
  1446.             SelectObject( hmemDC, pPictureData->hbitmapIcon ))) {
  1447.             GetObject( pPictureData->hbitmapIcon, sizeof( BITMAP ), &bm );
  1448.  
  1449.             BitBlt( ps.hdc, 0, 0, bm.bmWidth, bm.bmHeight,
  1450.                 hmemDC, 0, 0, SRCCOPY );
  1451.             SelectObject( hmemDC, hbitmapSave );
  1452.         }
  1453.         else {
  1454.             if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1455.                 FillRect( ps.hdc, &ps.rcPaint, hbrush );
  1456.                 DeleteObject( hbrush );
  1457.             }
  1458.  
  1459.             if( g.hpictIcon )
  1460.                 DrawIcon( ps.hdc, 2, 2, g.hpictIcon );
  1461.         }
  1462.  
  1463.         if( hmemDC )
  1464.             DeleteDC( hmemDC );
  1465.     }
  1466.  
  1467.     EndPaint( hwndPicture, &ps );
  1468.  
  1469.     return 0L;
  1470.  
  1471. }
  1472.  
  1473. // Function: BuildIconBitmap - builds the icon bitmap
  1474. // --------------------------------------------------------------------
  1475. // Parameters: HWND            hwndPicture     Handle of picture wnd
  1476. //             NPPICTUREDATA   pPictureData    -> picture data struct
  1477. //
  1478. // Returns:    LONG         0L
  1479. // --------------------------------------------------------------------
  1480. static BOOL NEAR BuildIconBitmap
  1481.                            ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  1482.  
  1483. {
  1484.     HDC              hdc;            // DC of picture
  1485.     HDC              hmemDC;         // Memory dc
  1486.     HBRUSH           hbrush;         // Temp background brush
  1487.     HBRUSH           hbrushSave;     // Prev brush
  1488.     HBITMAP          hbitmapSave;    // Prev bitmap
  1489.     HBITMAP          hbitmap;        // Handle of icon bitmap
  1490.     HGLOBAL          hbmi;           // Memory handle for DIB info struct
  1491.     HGLOBAL          hnewbmi;        // Temp memory handle
  1492.     BITMAPINFOHEADER bi;             // Bitmap info header struct
  1493.     LPVOID           lpbmi;          // -> bitmap info struct
  1494.     BITMAP           bm;             // BITMAP struct
  1495.     HPALETTE         hpalSave;       // Prev palette
  1496.     HCURSOR          hcursorSave;    // Prev cursor
  1497.     RECT             rcPicRect;      // Picture rect
  1498.     WORD             wIconBmpWidth;  // Icon width
  1499.     WORD             wIconBmpHeight; // Icon height
  1500.     WORD             wProportional;  // Temp
  1501.  
  1502.     static RECT      rcIcon = {
  1503.                          2, 2, 34, 34}; // Rect used in painting icon
  1504.     static RECT      rcPicbmp = {
  1505.                          4, 4, 32, 32}; // Rect used in painting pic
  1506.     static RECT      rcPicdib = {
  1507.                          0, 0, 28, 28}; // Rect used in painting pic
  1508.     static RECT      rcBitmap =         // Overall bitmap dimensions
  1509.                         {0, 0, 36, 36 };
  1510.  
  1511.  
  1512.     // Macro used to align on ULONG boundary
  1513.     // From 3.1 SDK sample code, dib.h
  1514.     #define WIDTHBYTES(i)  ( ( i + 31 ) / 32 * 4 )
  1515.  
  1516.     pPictureData->hbitmapIcon  = NULL;
  1517.     pPictureData->lpDIBIconMem = NULL;
  1518.  
  1519.     if( !( hdc = GetDC( hwndPicture ))) {
  1520.         return FALSE;
  1521.     }
  1522.  
  1523.     if( !( hmemDC = CreateCompatibleDC( hdc ))) {
  1524.         ReleaseDC( hwndPicture, hdc );
  1525.         return FALSE;
  1526.     }
  1527.  
  1528.     hbitmap  = NULL;
  1529.     hpalSave = NULL;
  1530.     hcursorSave = SetCursor( LoadCursor( NULL, IDC_WAIT ));
  1531.  
  1532.     // Get picture rect with proportions of the original pic
  1533.     rcPicRect = rcPicbmp;
  1534.     wIconBmpWidth  = rcPicbmp.right - rcPicbmp.left;
  1535.     wIconBmpHeight = rcPicbmp.bottom - rcPicbmp.top;
  1536.     if( pPictureData->idImageInfo.width >
  1537.         pPictureData->idImageInfo.height ) {
  1538.         wProportional = MulDiv( wIconBmpHeight,
  1539.             pPictureData->idImageInfo.width,
  1540.             pPictureData->idImageInfo.height );
  1541.         rcPicRect.left  -= ( wProportional - wIconBmpWidth ) / 2;
  1542.         rcPicRect.right = rcPicRect.left + wProportional;
  1543.     }
  1544.     else if( pPictureData->idImageInfo.width <
  1545.         pPictureData->idImageInfo.height ) {
  1546.         wProportional = MulDiv( wIconBmpWidth,
  1547.             pPictureData->idImageInfo.height,
  1548.             pPictureData->idImageInfo.width );
  1549.         rcPicRect.top   -= ( wProportional - wIconBmpHeight ) / 2;
  1550.         rcPicRect.bottom = rcPicRect.top + wProportional;
  1551.     }
  1552.  
  1553.     if( ( hbitmap = CreateCompatibleBitmap( hdc,
  1554.         rcBitmap.right, rcBitmap.bottom )) &&
  1555.         ( hbitmapSave = SelectObject( hmemDC, hbitmap ))) { //First fill the background
  1556.         if( hbrush = CreateSolidBrush( GetSysColor( COLOR_APPWORKSPACE ))) {
  1557.             FillRect( hmemDC, &rcBitmap, hbrush );
  1558.             DeleteObject( hbrush );
  1559.         }
  1560.  
  1561.         // Now draw the picture.
  1562.         // Keep picture inside the allowed rect
  1563.         SaveDC( hmemDC );
  1564.         IntersectClipRect( hmemDC, rcPicbmp.left, rcPicbmp.top,
  1565.             rcPicbmp.right, rcPicbmp.bottom );
  1566.  
  1567.         hbrushSave = SelectObject( hmemDC, PICBACKGRNDBRUSH );
  1568.         if( DrawPicture( hmemDC, pPictureData->phPicture, &rcPicRect, NULL )) {
  1569.             CommonTellUser( ViewerQueryResources(),
  1570.                 VIEWER_STRING_DRAWPICFAIL,
  1571.                 VIEWER_STRING_CAPTION, MB_OK );
  1572.         }
  1573.         SelectObject( hmemDC, hbrushSave );
  1574.         RestoreDC( hmemDC, -1 );
  1575.  
  1576.         // Now draw the picture frame
  1577.         if( g.hpictIcon )
  1578.             DrawIcon( hmemDC, 2, 2, g.hpictIcon );
  1579.  
  1580.         SelectObject( hmemDC, hbitmapSave );
  1581.  
  1582.         pPictureData->hbitmapIcon = hbitmap;
  1583.         hbitmap = NULL;
  1584.     }
  1585.     else {
  1586.         goto IconFailed;
  1587.     }
  1588.  
  1589.  
  1590.     if( ViewerIsPalettized()) // Palettized, use DIB bitmap, but only for picture
  1591.     { // Should always be a palette but test anyway
  1592.         if( pPictureData->hpalPicture &&
  1593.             !( hpalSave = SelectPalette
  1594.             ( hdc, pPictureData->hpalPicture, FALSE ))) {
  1595.             CommonTellUser( ViewerQueryResources(),
  1596.                 VIEWER_STRING_SELPALFAILED, NULL, MB_OK );
  1597.             goto IconFailed;
  1598.         }
  1599.  
  1600.         // Need to offset rcPicRect because of differences btwn
  1601.         // the origins of rcPicbmp and rcPicdib; ( 4, 4) vs ( 0, 0)
  1602.         OffsetRect( &rcPicRect, -rcPicbmp.left, -rcPicbmp.top );
  1603.  
  1604.         if( ( hbitmap = CreateCompatibleBitmap( hdc,
  1605.             rcPicdib.right, rcPicdib.bottom )) &&
  1606.             ( hbitmapSave = SelectObject( hmemDC, hbitmap ))) {
  1607.             hbrushSave = SelectObject( hmemDC, PICBACKGRNDBRUSH );
  1608.             if( DrawPicture( hmemDC, pPictureData->phPicture,
  1609.                 &rcPicRect, NULL )) {
  1610.                 CommonTellUser( ViewerQueryResources(),
  1611.                     VIEWER_STRING_DRAWPICFAIL,
  1612.                     VIEWER_STRING_CAPTION, MB_OK );
  1613.                 SelectObject( hmemDC, hbitmapSave );
  1614.                 SelectObject( hmemDC, hbrushSave );
  1615.                 goto IconFailed;
  1616.             }
  1617.             SelectObject( hmemDC, hbrushSave );
  1618.             SelectObject( hmemDC, hbitmapSave );
  1619.         }
  1620.         else {
  1621.             goto IconFailed;
  1622.         }
  1623.  
  1624.         // Now convert to DIB bitmap
  1625.         // Initialize bitmap info header struct
  1626.         GetObject( hbitmap, sizeof( BITMAP ), &bm );
  1627.  
  1628.         bi.biSize          = sizeof( BITMAPINFOHEADER );
  1629.         bi.biWidth         = bm.bmWidth;
  1630.         bi.biHeight        = bm.bmHeight;
  1631.         bi.biPlanes        = 1;
  1632.         bi.biBitCount      = bm.bmPlanes * bm.bmBitsPixel;
  1633.         bi.biCompression   = BI_RGB;
  1634.         bi.biSizeImage     = 0;
  1635.         bi.biXPelsPerMeter = 0;
  1636.         bi.biYPelsPerMeter = 0;
  1637.         bi.biClrUsed       = 0;
  1638.         bi.biClrImportant  = 0;
  1639.  
  1640.         if( !( hbmi = GlobalAlloc( GHND, bi.biSize + SIZE_COLOR_TABLE ))) {
  1641.             CommonTellUser( ViewerQueryResources(),
  1642.                 VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1643.             goto IconFailed;
  1644.         }
  1645.         lpbmi = (LPVOID) GlobalLock( hbmi );
  1646.  
  1647.         // First get bitmap size by using NULL argument
  1648.         *(LPBITMAPINFOHEADER) lpbmi = bi;
  1649.         GetDIBits( hdc, hbitmap, 0, bm.bmHeight, NULL,
  1650.             (LPBITMAPINFO) lpbmi, DIB_RGB_COLORS );
  1651.         bi = *(LPBITMAPINFOHEADER) lpbmi;
  1652.         // If driver failed to set size, make a guess
  1653.         if( bi.biSizeImage == 0 )
  1654.             bi.biSizeImage = bi.biHeight *
  1655.             WIDTHBYTES( (DWORD) bm.bmWidth * bi.biBitCount );
  1656.  
  1657.         // Now realloc to get space for bitmap bits
  1658.         GlobalUnlock( hbmi );
  1659.         if( !( hnewbmi = GlobalReAlloc( hbmi,
  1660.             bi.biSize + SIZE_COLOR_TABLE + bi.biSizeImage, GHND ))) {
  1661.             CommonTellUser( ViewerQueryResources(),
  1662.                 VIEWER_STRING_NOMEMORY, NULL, MB_OK );
  1663.             GlobalFree( hbmi );
  1664.             goto IconFailed;
  1665.         }
  1666.         hbmi = hnewbmi;
  1667.         lpbmi = (LPVOID) GlobalLock( hbmi );
  1668.  
  1669.         // Now get bitmap bits
  1670.         if( bm.bmHeight != GetDIBits( hdc, hbitmap, 0, bm.bmHeight,
  1671.             (LPVOID)((LPSTR) lpbmi + (WORD) bi.biSize + SIZE_COLOR_TABLE ),
  1672.             (LPBITMAPINFO) lpbmi, DIB_RGB_COLORS )) {
  1673.             CommonTellUser( ViewerQueryResources(),
  1674.                 VIEWER_STRING_NOMAKEDIB, NULL, MB_OK );
  1675.             GlobalUnlock( hbmi );
  1676.             GlobalFree( hbmi );
  1677.             goto IconFailed;
  1678.         }
  1679.  
  1680.         // Done. Save -> to DIB and toss device dependent bitmap
  1681.         pPictureData->lpDIBIconMem = (LPBITMAPINFO) lpbmi;
  1682.         DeleteObject( pPictureData->hbitmapIcon );
  1683.         pPictureData->hbitmapIcon  = NULL;
  1684.  
  1685.         DeleteObject( hbitmap );
  1686.         SelectPalette( hdc, hpalSave, FALSE );
  1687.     }
  1688.  
  1689.     SetCursor( hcursorSave );
  1690.     ReleaseDC( hwndPicture, hdc );
  1691.     DeleteDC ( hmemDC );
  1692.  
  1693.     return TRUE;
  1694.  
  1695.  IconFailed:
  1696.     if( hcursorSave )
  1697.         SetCursor( hcursorSave );
  1698.     if( hpalSave )
  1699.         SelectPalette( hdc, hpalSave, FALSE );
  1700.     if( hbitmap )
  1701.         DeleteObject( hbitmap );
  1702.  
  1703.     DeleteDC( hmemDC );
  1704.     ReleaseDC( hwndPicture, hdc );
  1705.  
  1706.     return FALSE;
  1707.  
  1708. }
  1709.  
  1710.  
  1711. // Function: StoreCurrentSystemPalette - stores the current system palette just
  1712. //                                       before calling RealizePalette.
  1713. //                                       This is also called during frame
  1714. //                                       wnd WM_PALETTECHANGED processing
  1715. // --------------------------------------------------------------------
  1716. // Parameters: HPALETTE      hpalPicture  Palette of picture that realized
  1717. //                           palette, otherwise NULL
  1718. //
  1719. // Returns:    VOID
  1720. // --------------------------------------------------------------------
  1721. VOID FAR StoreCurrentSystemPalette( HPALETTE hpalPicture )
  1722.  
  1723. {
  1724.     if( hpalPicture )
  1725.         g.hpalCurrentSystem = hpalPicture;
  1726.  
  1727.     return;
  1728. }
  1729.  
  1730.  
  1731. // Function: KeyDownMessage - processes the WM_KEYDOWN message
  1732. // --------------------------------------------------------------------
  1733. // Parameters: HWND         hwndPicture    Handle of picture window
  1734. //             WPARAM       wParam         WM_KEYDOWN wParam
  1735. //             LPARAM       lParam         WM_KEYDOWN lParam
  1736. //
  1737. // Returns:    LONG         Generally 0L
  1738. // --------------------------------------------------------------------
  1739. static LONG NEAR KeyDownMessage
  1740.                    ( HWND hwndPicture, WPARAM wParam, LPARAM lParam )
  1741.  
  1742. // Process keyboard interface messages
  1743.  
  1744. {
  1745.     NPPICTUREDATA   pPictureData; // -> picture data struct
  1746.     WORD            wScroll;      // Scrolling parameter
  1747.  
  1748.     switch( wParam ) {
  1749.         case VK_LEFT:
  1750.         case VK_RIGHT:
  1751.             if( ISKEYDOWN( VK_CONTROL ))
  1752.                 wScroll = ( wParam == VK_LEFT ) ? SB_PAGELEFT: SB_PAGERIGHT;
  1753.             else
  1754.                 wScroll = ( wParam == VK_LEFT ) ? SB_LINELEFT: SB_LINERIGHT;
  1755.  
  1756.             return ProcessHorzScroll( hwndPicture, wScroll, 0 );
  1757.  
  1758.         case VK_UP:
  1759.         case VK_DOWN:
  1760.             if( ISKEYDOWN( VK_CONTROL ))
  1761.                 wScroll = ( wParam == VK_UP ) ? SB_PAGEUP: SB_PAGEDOWN;
  1762.             else
  1763.                 wScroll = ( wParam == VK_UP ) ? SB_LINEUP: SB_LINEDOWN;
  1764.  
  1765.             return ProcessVertScroll( hwndPicture, wScroll, 0 );
  1766.  
  1767.         case VK_PRIOR:
  1768.         case VK_NEXT:
  1769.             if( ISKEYDOWN( VK_CONTROL ))
  1770.                 return ProcessHorzScroll( hwndPicture,
  1771.                 ( wParam == VK_PRIOR ? SB_PAGELEFT: SB_PAGERIGHT ), 0 );
  1772.             else
  1773.                 return ProcessVertScroll( hwndPicture,
  1774.                 ( wParam == VK_PRIOR ? SB_PAGEUP: SB_PAGEDOWN ), 0 );
  1775.  
  1776.         case VK_HOME:
  1777.         case VK_END:
  1778.             return ScrollToCorner( hwndPicture, wParam );
  1779.  
  1780.         case VK_ADD:
  1781.         case VK_SUBTRACT:
  1782.             if( (pPictureData = (NPPICTUREDATA)
  1783.                 GetWindowWord( hwndPicture, 0 )) &&
  1784.                 pPictureData->zsZoomScroll.hwnd )
  1785.                 return SendMessage( pPictureData->zsZoomScroll.hwnd,
  1786.                 WM_KEYDOWN, wParam, lParam );
  1787.             break;
  1788.  
  1789.     }
  1790.  
  1791.     return 0L;
  1792.  
  1793. }
  1794.  
  1795.  
  1796. // Function: PrintPicture - prints indicated number of copies of
  1797. //                          the picture
  1798. // --------------------------------------------------------------------
  1799. // Parameters: HWND         hwndPicture     Handle of Picture window
  1800. //             LPPRINTDLG   lppd            -> to PRINTDLG struct created
  1801. //                                          by print common dialog
  1802. //
  1803. // Returns:    LONG         0L if successful
  1804. // --------------------------------------------------------------------
  1805. static LONG NEAR PrintPicture( HWND hwndPicture, LPPRINTDLG lppd )
  1806.  
  1807. {
  1808.     NPPICTUREDATA   pPictureData; // -> picture data struct
  1809.     WORD            i;            // Counter
  1810.     DOCINFO         diDocInfo;    // Document info struct
  1811.     BOOL            bError;       // Error flag
  1812.     RECT            rcPicture;    // Picture rect
  1813.     int             nError;       // Error return
  1814.     int             xRes;         // Horz printer resolution
  1815.     int             yRes;         // Vert printer resolution
  1816.     int             xOffset;      // Horz offset to center picture
  1817.     int             yOffset;      // Vert offset to center picture
  1818.     OSErr           oserr;        // Error return from DrawPictureFile
  1819.     WORD            wWidthPage;   // Width of printed page in pixels
  1820.     WORD            wHeightPage;  // Height of printed page in pixels
  1821.  
  1822.  
  1823.     if( !(pPictureData =
  1824.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  1825.         CommonTellUser( ViewerQueryResources(),
  1826.             VIEWER_STRING_NOPICDATA, NULL, MB_OK );
  1827.         // Turn off not reported flag
  1828.         return SP_ERROR &  ~SP_NOTREPORTED;
  1829.     }
  1830.  
  1831.     diDocInfo.cbSize      = sizeof( DOCINFO );
  1832.     diDocInfo.lpszDocName = pPictureData->szPictureName;
  1833.     diDocInfo.lpszOutput  = (LPSTR) NULL;
  1834.  
  1835.     bError = FALSE;
  1836.     oserr  = 0L;
  1837.     nError = SP_ERROR;
  1838.  
  1839.     wWidthPage  = GetDeviceCaps( lppd->hDC, HORZRES );
  1840.     wHeightPage = GetDeviceCaps( lppd->hDC, VERTRES );
  1841.  
  1842.     // get resolution of printer
  1843.     xRes = MulDiv( wWidthPage, 254,
  1844.         GetDeviceCaps( lppd->hDC, HORZSIZE ) * 10 );
  1845.     yRes = MulDiv( wHeightPage, 254,
  1846.         GetDeviceCaps( lppd->hDC, VERTSIZE ) * 10 );
  1847.  
  1848.     // Scale picture rect for differences in resolution
  1849.     rcPicture.right  = MulDiv( pPictureData->idImageInfo.width,
  1850.         xRes, HIWORD( pPictureData->idImageInfo.hRes ));
  1851.     rcPicture.bottom = MulDiv( pPictureData->idImageInfo.height,
  1852.         yRes, HIWORD( pPictureData->idImageInfo.vRes ));
  1853.     rcPicture.left = rcPicture.top = 0;
  1854.  
  1855.     // Now make sure that picture fits on page
  1856.     if( rcPicture.right > (int) wWidthPage ) {
  1857.         rcPicture.bottom = MulDiv( rcPicture.bottom,
  1858.             wWidthPage, rcPicture.right );
  1859.         rcPicture.right = wWidthPage;
  1860.     }
  1861.     if( rcPicture.bottom > (int) wHeightPage ) {
  1862.         rcPicture.right = MulDiv( rcPicture.right,
  1863.             wHeightPage, rcPicture.bottom );
  1864.         rcPicture.bottom = wHeightPage;
  1865.     }
  1866.  
  1867.     // Now center rect on page
  1868.     xOffset = ( wWidthPage  - rcPicture.right ) / 2;
  1869.     yOffset = ( wHeightPage - rcPicture.bottom ) / 2;
  1870.     OffsetRect( &rcPicture, xOffset, yOffset );
  1871.  
  1872.     // Start printing. Loop over number of copies
  1873.     if( StartDoc( lppd->hDC, &diDocInfo ) > 0 ) {
  1874.         for( i=0; (i < lppd->nCopies) && !bError; i++) {
  1875.             if( StartPage( lppd->hDC ) > 0 ) {
  1876.                 if( (oserr = DrawPicture( lppd->hDC,
  1877.                     pPictureData->phPicture, &rcPicture, NULL )) != 0L ) { // DrawPicture failed, abort the print
  1878.                     AbortDoc( lppd->hDC );
  1879.                     bError = TRUE;
  1880.                 }
  1881.                 else {
  1882.                     if( ( nError = EndPage( lppd->hDC )) < 0 )
  1883.                         bError = TRUE;
  1884.                 }
  1885.             }
  1886.             else
  1887.                 bError = TRUE;
  1888.         }
  1889.     }
  1890.     else
  1891.         bError = TRUE;
  1892.  
  1893.     if( !bError )
  1894.         EndDoc( lppd->hDC );
  1895.     else if( oserr ) {
  1896.         CommonTellUser( ViewerQueryResources(),
  1897.             VIEWER_STRING_DRAWPICFAIL,
  1898.             VIEWER_STRING_PRT_CAPTION, MB_OK );
  1899.         // Error has been reported, turn off "not reported" bit
  1900.         nError = SP_ERROR &  ~SP_NOTREPORTED;
  1901.     }
  1902.  
  1903.     return (LONG) nError;
  1904. }
  1905.  
  1906.  
  1907. // Function: GetInfoDlgProc - Get Info dialog proc
  1908. // --------------------------------------------------------------------
  1909. // Parameters: As required by Microsoft Windows
  1910. //
  1911. // Returns:    As required by Microsoft Windows
  1912. // --------------------------------------------------------------------
  1913. BOOL __export CALLBACK GetInfoDlgProc
  1914.     ( HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1915.  
  1916. {
  1917.     NPPICTUREDATA  pPictureData; // -> picture data struct
  1918.     HWND           hwndPicture;  // Handle to picture window
  1919.     HWND           hwndCtl;      // Handle of control
  1920.     HDC            hdc;          // DC of control
  1921.     int            nHeight;      // Text height
  1922.  
  1923.  
  1924.     switch( msg ) {
  1925.         case WM_INITDIALOG:
  1926.             hwndPicture = (HWND) SendMessage
  1927.                 ( ViewerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  1928.  
  1929.             // Use property to associate picture window handle with
  1930.             // info dialog. This is necessary because MDI makes frame
  1931.             // window the parent of all dialogs no matter what handle
  1932.             // is used in the CreateDialog call
  1933.             SetProp( hdlg, GETINFOPICTUREPROP, (HANDLE) hwndPicture );
  1934.  
  1935.  
  1936.             if( pPictureData = (NPPICTUREDATA)
  1937.                 GetWindowWord( hwndPicture, 0 )) {
  1938.                 pPictureData->hwndGetInfo = hdlg;
  1939.  
  1940.                 if( hdc = GetDC( hdlg )) {
  1941.                     nHeight = -MulDiv( 8, GetDeviceCaps( hdc, LOGPIXELSY ), 72 );
  1942.                     if( pPictureData->hfInfo = MakeAnArialFont( hdc, nHeight )) {
  1943.                         hwndCtl = GetWindow( hdlg, GW_CHILD );
  1944.                         while( hwndCtl ) {
  1945.                             if( GetDlgCtrlID( hwndCtl ) != IDOK )
  1946.                                 SendMessage( hwndCtl, WM_SETFONT,
  1947.                                 (WPARAM) pPictureData->hfInfo, 0 );
  1948.                             hwndCtl = GetWindow( hwndCtl, GW_HWNDNEXT );
  1949.                         }
  1950.                     }
  1951.                     ReleaseDC( hdlg, hdc );
  1952.                 }
  1953.  
  1954.                 FillPictureInfo( hdlg, pPictureData );
  1955.             }
  1956.  
  1957.             return TRUE;
  1958.  
  1959.         case WM_ACTIVATE:
  1960.             ViewerSetActiveModeless( wParam, hdlg );
  1961.             return TRUE;
  1962.  
  1963.         case WM_COMMAND:
  1964.             return DestroyWindow( hdlg );
  1965.  
  1966.         // WM_USER messages
  1967.  
  1968.         case WM_INFO_UPDATEFILENAME:
  1969.             hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1970.             if( pPictureData = (NPPICTUREDATA)
  1971.                 GetWindowWord( hwndPicture, 0 ))
  1972.                 UpdateInfoFileName( hdlg, pPictureData );
  1973.  
  1974.             break;
  1975.  
  1976.         case WM_INFO_CURRENTSIZE:
  1977.             hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1978.             if( pPictureData = (NPPICTUREDATA)
  1979.                 GetWindowWord( hwndPicture, 0 ))
  1980.                 UpdateInfoCurrentSize( hdlg, pPictureData );
  1981.  
  1982.             break;
  1983.  
  1984.         // end WM_USER messages
  1985.  
  1986.         case WM_DESTROY:
  1987.             hwndPicture = (HWND) GetProp( hdlg, GETINFOPICTUREPROP );
  1988.             if( IsWindow( hwndPicture ) && ( pPictureData =
  1989.                 (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  1990.                 pPictureData->hwndGetInfo = NULL;
  1991.  
  1992.                 if( pPictureData->hfInfo )
  1993.                     DeleteObject( pPictureData->hfInfo );
  1994.                 pPictureData->hfInfo = NULL;
  1995.             }
  1996.  
  1997.             RemoveProp( hdlg, GETINFOPICTUREPROP );
  1998.  
  1999.             return FALSE;
  2000.     }
  2001.  
  2002.     return FALSE;
  2003.  
  2004. }
  2005.  
  2006.  
  2007. // Function: FillPictureInfo - Fills dialog controls with picture data
  2008. // --------------------- -----------------------------------------------
  2009. // Parameters: HWND           hdlg             Handle of dialog wnd
  2010. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2011. //
  2012. // Returns:    VOID
  2013. // --------------------------------------------------------------------
  2014. static VOID NEAR FillPictureInfo( HWND hdlg, NPPICTUREDATA pPictureData )
  2015.  
  2016. {
  2017.     char      szBuffer[50];  // buffer
  2018.     char      szFormat[20];  // Format buffer
  2019.     WORD      wNormalWidth;  // Normal width of picture
  2020.     WORD      wNormalHeight; // Normal height of picture
  2021.     DWORD     dwColors;      // Number of colors
  2022.     DWORD     dwSize;        // Uncompressed size
  2023.     WORD      wIDString;     // Resource string id
  2024.  
  2025.  
  2026.     // Picture name: Append duplication index if > 0
  2027.     UpdateInfoFileName( hdlg, pPictureData );
  2028.  
  2029.     // Filesize
  2030.     SetDlgItemText( hdlg, IMAGE_INFO_FILESIZE,
  2031.         (LPSTR) pPictureData->szFileSizeOnDisk );
  2032.  
  2033.     // Current Width and Height
  2034.     UpdateInfoCurrentSize( hdlg, pPictureData );
  2035.  
  2036.     // Normal Width and Height
  2037.     wNormalWidth  = pPictureData->idImageInfo.width;
  2038.     wNormalHeight = pPictureData->idImageInfo.height;
  2039.     LoadString( ViewerQueryResources(), VIEWER_STRING_WANDH,
  2040.         szFormat, sizeof( szFormat ));
  2041.     wsprintf( szBuffer, szFormat, wNormalWidth, wNormalHeight );
  2042.     SetDlgItemText( hdlg, IMAGE_INFO_WANDH, szBuffer );
  2043.  
  2044.  
  2045.     // Resolution
  2046.     if( ((LONG) pPictureData->idImageInfo.hRes == -1L ) ||
  2047.         ((LONG) pPictureData->idImageInfo.hRes == 0L ))
  2048.         LoadString( ViewerQueryResources(),
  2049.         VIEWER_STRING_NORESOLUTION, szBuffer, sizeof( szBuffer ));
  2050.     else {
  2051.         LoadString( ViewerQueryResources(),
  2052.             VIEWER_STRING_RESOLUTION, szFormat, sizeof( szFormat ));
  2053.         wsprintf( szBuffer, szFormat,
  2054.             HIWORD( pPictureData->idImageInfo.hRes ));
  2055.     }
  2056.     SetDlgItemText( hdlg, IMAGE_INFO_RESOLUTION, szBuffer );
  2057.  
  2058.     // Normal colors
  2059.     switch( pPictureData->idImageInfo.depth ) {
  2060.         case 1:      // Black and White
  2061.             wIDString = VIEWER_STRING_CLRS_BANDW;      
  2062.             break;
  2063.         case 1 + 32: // 2 Grays
  2064.             wIDString = VIEWER_STRING_CLRS_2GRAYS;     
  2065.             break;
  2066.         case 2:      // 4 Colors
  2067.             wIDString = VIEWER_STRING_CLRS_4COLORS;    
  2068.             break;
  2069.         case 2 + 32: // 4 Grays
  2070.             wIDString = VIEWER_STRING_CLRS_4GRAYS;     
  2071.             break;
  2072.         case 4:      // 16 Colors
  2073.             wIDString = VIEWER_STRING_CLRS_16COLORS;   
  2074.             break;
  2075.         case 4 + 32: // 16 Grays
  2076.             wIDString = VIEWER_STRING_CLRS_16GRAYS;    
  2077.             break;
  2078.         case 8:      // 256 Colors
  2079.             wIDString = VIEWER_STRING_CLRS_256COLORS;  
  2080.             break;
  2081.         case 8 + 32: // 256 Grays
  2082.             wIDString = VIEWER_STRING_CLRS_256GRAYS;   
  2083.             break;
  2084.         case 16:     // Thousands of Colors
  2085.             wIDString = VIEWER_STRING_CLRS_THOUSANDS;  
  2086.             break;
  2087.         case 24:     // Millions of Colors
  2088.             wIDString = VIEWER_STRING_CLRS_MILLIONS;   
  2089.             break;
  2090.         case 32:     // Millions of Colors+
  2091.             wIDString = VIEWER_STRING_CLRS_MILLNSPLUS; 
  2092.             break;
  2093.         default:
  2094.             wIDString = 0xffff;
  2095.             if( pPictureData->idImageInfo.depth < 32 ) {
  2096.                 LoadString( ViewerQueryResources(),
  2097.                     VIEWER_STRING_COLORS, szFormat, sizeof( szFormat ));
  2098.                 dwColors = 1L << pPictureData->idImageInfo.depth;
  2099.                 wsprintf( szBuffer, szFormat, dwColors );
  2100.             }
  2101.             else {
  2102.                 szBuffer[0] = '\0';
  2103.             }
  2104.             break;
  2105.     }
  2106.     if( wIDString != 0xffff )
  2107.         LoadString( ViewerQueryResources(),
  2108.         wIDString, szBuffer, sizeof( szBuffer ));
  2109.     SetDlgItemText( hdlg, IMAGE_INFO_COLORS, szBuffer );
  2110.  
  2111.  
  2112.     // Compressor. Compressor type displayed is the string stored for use in
  2113.     //             the banner bar rather that the DWORD value such as 'jpeg'
  2114.     SetDlgItemText( hdlg, IMAGE_INFO_COMPRESSOR,
  2115.         pPictureData->szPictType );
  2116.  
  2117.  
  2118.     // Quality
  2119.     if( pPictureData->idImageInfo.CodecType ) {
  2120.         *((PDWORD) &szBuffer) = pPictureData->idImageInfo.CodecType;
  2121.         szBuffer[ sizeof(DWORD) ] = '\0';
  2122.     }
  2123.     if( !pPictureData->idImageInfo.CodecType ||
  2124.         !lstrcmpi( szBuffer, "raw " )) {
  2125.         szBuffer[0] = '\0';
  2126.     }
  2127.     else {
  2128.         LoadString( ViewerQueryResources(),
  2129.             VIEWER_STRING_QUALITY, szBuffer, sizeof( szBuffer ));
  2130.     }
  2131.     SetDlgItemText( hdlg, IMAGE_INFO_QUALITY, szBuffer );
  2132.  
  2133.  
  2134.     // Uncompressed size
  2135.     dwSize = ( (DWORD) wNormalWidth * wNormalHeight *
  2136.         pPictureData->idImageInfo.depth ) / 8L;
  2137.     if( dwSize < 1000L ) {
  2138.         wIDString = VIEWER_STRING_SIZEBYTES;
  2139.     }
  2140.     else {
  2141.         dwSize /= 1000L;
  2142.         wIDString = VIEWER_STRING_SIZEKBYTES;
  2143.     }
  2144.  
  2145.     LoadString( ViewerQueryResources(), wIDString,
  2146.         szFormat, sizeof( szFormat ));
  2147.     wsprintf( szBuffer, szFormat, dwSize );
  2148.     SetDlgItemText( hdlg, IMAGE_INFO_UNCOMPSIZE, szBuffer );
  2149.  
  2150.     return;
  2151. }
  2152.  
  2153.  
  2154. // Function: UpdateInfoFileName - Updates the file name with the current
  2155. //                                instance count in the info dialog
  2156. // --------------------- -----------------------------------------------
  2157. // Parameters: HWND           hdlg             Handle of dialog wnd
  2158. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2159. //
  2160. // Returns:    VOID
  2161. // --------------------------------------------------------------------
  2162. static VOID NEAR UpdateInfoFileName
  2163.                         ( HWND hdlg, NPPICTUREDATA pPictureData )
  2164.  
  2165. {
  2166.     char      szBuffer[MAX_NAME_LEN + 10]; // Name buffer
  2167.     char      szFormat[20];                // Format buffer
  2168.  
  2169.     lstrcpy( szFormat, "%s%s" );
  2170.     if( pPictureData->wDuplicationIndex > 0 )
  2171.         lstrcat( szFormat, ":%u" );
  2172.     wsprintf( szBuffer, szFormat, (LPSTR) pPictureData->szPictureName,
  2173.         (LPSTR) pPictureData->szPictureExt,
  2174.         pPictureData->wDuplicationIndex );
  2175.     AnsiUpper( szBuffer );
  2176.     SetDlgItemText( hdlg, IMAGE_INFO_NAME, (LPSTR) szBuffer );
  2177.  
  2178.     return;
  2179. }
  2180.  
  2181. // Function: UpdateInfoCurrentSize - Updates the current size in the
  2182. //                                   info dialog
  2183. // --------------------- -----------------------------------------------
  2184. // Parameters: HWND           hdlg             Handle of dialog wnd
  2185. //             NPPICTUREDATA  pPictureData     -> to PICTUREDATA struct
  2186. //
  2187. // Returns:    VOID
  2188. // --------------------------------------------------------------------
  2189. static VOID NEAR UpdateInfoCurrentSize
  2190.                         ( HWND hdlg, NPPICTUREDATA pPictureData )
  2191.  
  2192. {
  2193.     char      szBuffer[50]; // buffer
  2194.     char      szFormat[20]; // Format buffer
  2195.  
  2196.     LoadString( ViewerQueryResources(), VIEWER_STRING_WANDH,
  2197.         szFormat, sizeof( szFormat ));
  2198.     wsprintf( szBuffer, szFormat,
  2199.         pPictureData->rcCurPictureRect.right -
  2200.         pPictureData->rcCurPictureRect.left,
  2201.         pPictureData->rcCurPictureRect.bottom -
  2202.         pPictureData->rcCurPictureRect.top );
  2203.     SetDlgItemText( hdlg, IMAGE_INFO_CURSIZE, szBuffer );
  2204.  
  2205.     return;
  2206. }
  2207.  
  2208.  
  2209. // Function: InitializePopupMenus - Called just before the popup menus
  2210. //                                  are displayed
  2211. // --------------------------------------------------------------------
  2212. // Parameters: HWND         hwndPicture     Handle of Picture window
  2213. //             HMENU        hmenuPopup      Handle of popup menu
  2214. //             int          nPopupIndex     Index of popup
  2215. //
  2216. // Returns:    LONG         0L if successful
  2217. // --------------------------------------------------------------------
  2218. static LONG NEAR InitializePopupMenus
  2219.                 ( HWND hwndPicture, HMENU hmenuPopup, int nPopupIndex )
  2220.  
  2221. {
  2222.     NPPICTUREDATA    pPictureData;      // -> picture data struct
  2223.     char             szTitle[64];       // OLE Client doc title
  2224.     char             szItemFormat1[32]; // Item format string
  2225.     char             szItem1[128];      // New item string
  2226.     char             szItemFormat2[32]; // Item format string
  2227.     char             szItem2[128];      // New item string
  2228.  
  2229.     if( !(pPictureData =
  2230.         (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))) {
  2231.         CommonTellUser( ViewerQueryResources(),
  2232.             VIEWER_STRING_NOPICDATA, VIEWER_STRING_CAPTION, MB_OK );
  2233.         return 0L;
  2234.     }
  2235.  
  2236.     // Decrement index if maximized since MDI adds a system menu item
  2237.     // which puts count off by one
  2238.     if( IsZoomed( hwndPicture ))
  2239.         nPopupIndex--;
  2240.  
  2241.     if( nPopupIndex == MENU_FILE_POS ) { // See if wnd is an activated client object
  2242.         if( QTOLE_IsActiveObjectWnd
  2243.             ( ViewerQueryOleData(), hwndPicture, szTitle )) {
  2244.             LoadString( ViewerQueryResources(),
  2245.                 VIEWER_STRING_OLECLOSE, szItemFormat1, sizeof( szItemFormat1 ));
  2246.             wsprintf( szItem1, szItemFormat1, (LPSTR) szTitle );
  2247.  
  2248.             LoadString( ViewerQueryResources(),
  2249.                 VIEWER_STRING_OLEEXIT, szItemFormat2, sizeof( szItemFormat2 ));
  2250.             wsprintf( szItem2, szItemFormat2, (LPSTR) szTitle );
  2251.         }
  2252.         else {
  2253.             LoadString( ViewerQueryResources(),
  2254.                 VIEWER_STRING_CLOSE, szItem1, sizeof( szItem1 ));
  2255.             LoadString( ViewerQueryResources(),
  2256.                 VIEWER_STRING_EXIT, szItem2, sizeof( szItem2 ));
  2257.         }
  2258.  
  2259.         DeleteMenu( hmenuPopup, VIEWER_FILE_CLOSE, MF_BYCOMMAND );
  2260.         InsertMenu( hmenuPopup, 1, MF_BYPOSITION,
  2261.             VIEWER_FILE_CLOSE, szItem1 );
  2262.         DeleteMenu( hmenuPopup, VIEWER_FILE_EXIT, MF_BYCOMMAND );
  2263.         InsertMenu( hmenuPopup, (UINT) -1, MF_BYPOSITION,
  2264.             VIEWER_FILE_EXIT, szItem2 );
  2265.     }
  2266.     else if( nPopupIndex == MENU_EDIT_POS ) {
  2267.         EnableMenuItem( hmenuPopup, VIEWER_EDIT_COPYPICTURE,
  2268.             ( IsIconic( hwndPicture ) ?  MF_GRAYED: MF_ENABLED ) |
  2269.             MF_BYCOMMAND );
  2270.         EnableMenuItem( hmenuPopup, VIEWER_EDIT_OPTIONS,
  2271.             ( IsIconic( hwndPicture ) ) ? MF_GRAYED: MF_ENABLED );
  2272.         EnableMenuItem( hmenuPopup, VIEWER_EDIT_CANCELSEL,
  2273.             ( IsRectEmpty( &pPictureData->qtoleOptions.rcSelection ))?
  2274.             MF_GRAYED: MF_ENABLED );
  2275.     }
  2276.     else if( nPopupIndex == MENU_IMAGE_POS ) {
  2277.         CheckMenuItem( hmenuPopup, VIEWER_IMAGE_HALFSIZE,
  2278.             ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2279.             VIEWER_IMAGE_HALFSIZE) ? MF_CHECKED: MF_UNCHECKED );
  2280.         CheckMenuItem( hmenuPopup, VIEWER_IMAGE_NORMALSIZE,
  2281.             ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2282.             VIEWER_IMAGE_NORMALSIZE) ? MF_CHECKED: MF_UNCHECKED );
  2283.         CheckMenuItem( hmenuPopup, VIEWER_IMAGE_DOUBLESIZE,
  2284.             ( pPictureData->zsZoomScroll.wCurZoomIndex ==
  2285.             VIEWER_IMAGE_DOUBLESIZE) ? MF_CHECKED: MF_UNCHECKED );
  2286.     }
  2287.  
  2288.     return 0L;
  2289. }
  2290.  
  2291.  
  2292.  
  2293. // Function: SetOptionsDefaults - Set option defaults
  2294. // --------------------------------------------------------------------
  2295. // Parameters: HWND             hwndPicture      Picture hwnd
  2296. //             NPPICTUREDATA    pPictureData     -> picture data struct
  2297. //
  2298. // Returns:    VOID
  2299. // --------------------------------------------------------------------
  2300. static VOID NEAR SetOptionsDefaults
  2301.                          ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  2302.  
  2303. { // Preset copy struct parameters that do not change
  2304.     pPictureData->qtoleOptions.lStructSize   = sizeof( QTOLE_OPTIONSPICTURE );
  2305.     pPictureData->qtoleOptions.lVersion      = VERSION_1;
  2306.     pPictureData->qtoleOptions.wObjectType   = PICTURE_OBJECT;
  2307.     pPictureData->qtoleOptions.hwndObject    = hwndPicture;
  2308.  
  2309.     pPictureData->qtoleOptions.phPicture     = pPictureData->phPicture;
  2310.  
  2311.     // Query qtw.ini for defaults
  2312.     ViewerGetDefaultOptions( &pPictureData->qtoleOptions );
  2313.  
  2314.     lstrcpy( pPictureData->qtoleOptions.szCaption, pPictureData->szPictureName );
  2315.     lstrcat( pPictureData->qtoleOptions.szCaption, pPictureData->szPictureExt );
  2316.  
  2317.     return;
  2318. }
  2319.  
  2320.  
  2321. // Function: UpdatePictForOptions - Sets the picture according to values set
  2322. //                                  in options struct
  2323. // --------------------------------------------------------------------
  2324. // Parameters: HWND          hwndPicture      Picture window handle
  2325. //             NPPICTUREDATA pPictureData     Picture data structure
  2326. //             BOOL          bCalledByOLE     TRUE if called by ole callback funct.
  2327. //
  2328. // Returns:    None
  2329. // --------------------------------------------------------------------
  2330. VOID FAR UpdatePictForOptions
  2331.     ( HWND hwndPicture, NPPICTUREDATA pPictureData, BOOL bCalledByOLE )
  2332.  
  2333. {
  2334.     LPQTOLE_OPTIONSPICTURE  lpOptions;
  2335.     POINT                   ptUL;
  2336.     WORD                    wZoomIndex;
  2337.  
  2338.     lpOptions = &pPictureData->qtoleOptions;
  2339.     if( lpOptions->bZoomHalf )
  2340.         SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_HALFSIZE, 0L );
  2341.     else if( lpOptions->bZoomNormal )
  2342.         SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_NORMALSIZE, 0L );
  2343.     else if( lpOptions->bZoomDouble )
  2344.         SendMessage( hwndPicture, WM_COMMAND, VIEWER_IMAGE_DOUBLESIZE, 0L );
  2345.     else if( bCalledByOLE ) {
  2346.         wZoomIndex = ViewerQueryZoomIndex( lpOptions->wZoomCurrent );
  2347.         ZoomPicture( hwndPicture, wZoomIndex );
  2348.  
  2349.         if( !IsRectEmpty( &lpOptions->rcSelection )) {
  2350.             ptUL = *(LPPOINT) &lpOptions->rcSelection.left;
  2351.             ptUL.x = MulDiv( ptUL.x, (int) lpOptions->wZoomCurrent, 100 );
  2352.             ptUL.y = MulDiv( ptUL.y, (int) lpOptions->wZoomCurrent, 100 );
  2353.  
  2354.             ProcessHorzScroll( hwndPicture, SB_THUMBPOSITION, ptUL.x );
  2355.             ProcessVertScroll( hwndPicture, SB_THUMBPOSITION, ptUL.y );
  2356.  
  2357.             InvalidateRect( hwndPicture, NULL, TRUE );
  2358.         }
  2359.     }
  2360.  
  2361.     return;
  2362. }
  2363.  
  2364.  
  2365. // Function: PopulateOptionsStruct - Populated the options structure
  2366. // --------------------------------------------------------------------
  2367. // Parameters: HWND          hwndPicture      Picture window handle
  2368. //             NPPICTUREDATA pPictureData     Picture data structure
  2369. //
  2370. // Returns:    None
  2371. // --------------------------------------------------------------------
  2372. static VOID NEAR PopulateOptionsStruct
  2373.                       ( HWND hwndPicture, NPPICTUREDATA pPictureData )
  2374.  
  2375. { // Update these each time in case they get NULLed somewhere
  2376.     pPictureData->qtoleOptions.hwndObject = hwndPicture;
  2377.     pPictureData->qtoleOptions.phPicture  = pPictureData->phPicture;
  2378.  
  2379.     if( pPictureData->qtoleOptions.bZoomHalf )
  2380.         pPictureData->qtoleOptions.wZoomCurrent = 50;
  2381.     else if( pPictureData->qtoleOptions.bZoomNormal )
  2382.         pPictureData->qtoleOptions.wZoomCurrent = 100;
  2383.     else if( pPictureData->qtoleOptions.bZoomDouble )
  2384.         pPictureData->qtoleOptions.wZoomCurrent = 200;
  2385.     else
  2386.         pPictureData->qtoleOptions.wZoomCurrent =
  2387.         ViewerQueryZoomMultiplier
  2388.         ( pPictureData->zsZoomScroll.wCurZoomIndex );
  2389.     return;
  2390. }
  2391.  
  2392.  
  2393. //  The remaining functions are the query functions called by other modules
  2394.  
  2395. // Function: ViewerQueryActivePictureName - Query name of active picture
  2396. // --------------------------------------------------------------------
  2397. // Parameters: LPSTR      lpBuffer       string buffer
  2398. //
  2399. // Returns:    LPSTR      lpBuffer       Name of active picture
  2400. // --------------------------------------------------------------------
  2401. LPSTR FAR ViewerQueryActivePictureName( LPSTR lpBuffer )
  2402.  
  2403. {
  2404.     HWND            hwndPicture;  // Handle to active window
  2405.     NPPICTUREDATA   pPictureData; // -> picture data struct
  2406.  
  2407.     hwndPicture = (HWND) SendMessage
  2408.         ( ViewerQueryClientWindow(), WM_MDIGETACTIVE, 0, 0L );
  2409.     *lpBuffer = 0;
  2410.     if( pPictureData = (NPPICTUREDATA) GetWindowWord( hwndPicture, 0 ))
  2411.         lstrcpy( lpBuffer, pPictureData->szPictureName );
  2412.  
  2413.     return lpBuffer;
  2414. }
  2415.  
  2416.